Django

Code

root/django/trunk/django/contrib/databrowse/datastructures.py

Revision 7061, 9.1 kB (checked in by mtredinnick, 10 months ago)

Fixed #6356 -- Added a mark_safe() call that was missed in a url() method. Thanks, tangerine.

  • Property svn:eol-style set to native
Line 
1 """
2 These classes are light wrappers around Django's database API that provide
3 convenience functionality and permalink functions for the databrowse app.
4 """
5
6 from django.db import models
7 from django.utils import dateformat
8 from django.utils.text import capfirst
9 from django.utils.translation import get_date_formats
10 from django.utils.encoding import smart_unicode, smart_str, iri_to_uri
11 from django.utils.safestring import mark_safe
12 from django.db.models.query import QuerySet
13
14 EMPTY_VALUE = '(None)'
15 DISPLAY_SIZE = 100
16
17 class EasyModel(object):
18     def __init__(self, site, model):
19         self.site = site
20         self.model = model
21         self.model_list = site.registry.keys()
22         self.verbose_name = model._meta.verbose_name
23         self.verbose_name_plural = model._meta.verbose_name_plural
24
25     def __repr__(self):
26         return '<EasyModel for %s>' % smart_str(self.model._meta.object_name)
27
28     def model_databrowse(self):
29         "Returns the ModelDatabrowse class for this model."
30         return self.site.registry[self.model]
31
32     def url(self):
33         return mark_safe('%s%s/%s/' % (self.site.root_url, self.model._meta.app_label, self.model._meta.module_name))
34
35     def objects(self, **kwargs):
36         return self.get_query_set().filter(**kwargs)
37
38     def get_query_set(self):
39         easy_qs = self.model._default_manager.get_query_set()._clone(klass=EasyQuerySet)
40         easy_qs._easymodel = self
41         return easy_qs
42
43     def object_by_pk(self, pk):
44         return EasyInstance(self, self.model._default_manager.get(pk=pk))
45
46     def sample_objects(self):
47         for obj in self.model._default_manager.all()[:3]:
48             yield EasyInstance(self, obj)
49
50     def field(self, name):
51         try:
52             f = self.model._meta.get_field(name)
53         except models.FieldDoesNotExist:
54             return None
55         return EasyField(self, f)
56
57     def fields(self):
58         return [EasyField(self, f) for f in (self.model._meta.fields + self.model._meta.many_to_many)]
59
60 class EasyField(object):
61     def __init__(self, easy_model, field):
62         self.model, self.field = easy_model, field
63
64     def __repr__(self):
65         return smart_str(u'<EasyField for %s.%s>' % (self.model.model._meta.object_name, self.field.name))
66
67     def choices(self):
68         for value, label in self.field.choices:
69             yield EasyChoice(self.model, self, value, label)
70
71     def url(self):
72         if self.field.choices:
73             return mark_safe('%s%s/%s/%s/' % (self.model.site.root_url, self.model.model._meta.app_label, self.model.model._meta.module_name, self.field.name))
74         elif self.field.rel:
75             return mark_safe('%s%s/%s/' % (self.model.site.root_url, self.model.model._meta.app_label, self.model.model._meta.module_name))
76
77 class EasyChoice(object):
78     def __init__(self, easy_model, field, value, label):
79         self.model, self.field = easy_model, field
80         self.value, self.label = value, label
81
82     def __repr__(self):
83         return smart_str(u'<EasyChoice for %s.%s>' % (self.model.model._meta.object_name, self.field.name))
84
85     def url(self):
86         return mark_safe('%s%s/%s/%s/%s/' % (self.model.site.root_url, self.model.model._meta.app_label, self.model.model._meta.module_name, self.field.field.name, iri_to_uri(self.value)))
87
88 class EasyInstance(object):
89     def __init__(self, easy_model, instance):
90         self.model, self.instance = easy_model, instance
91
92     def __repr__(self):
93         return smart_str(u'<EasyInstance for %s (%s)>' % (self.model.model._meta.object_name, self.instance._get_pk_val()))
94
95     def __unicode__(self):
96         val = smart_unicode(self.instance)
97         if len(val) > DISPLAY_SIZE:
98             return val[:DISPLAY_SIZE] + u'...'
99         return val
100
101     def __str__(self):
102         return self.__unicode__().encode('utf-8')
103
104     def pk(self):
105         return self.instance._get_pk_val()
106
107     def url(self):
108         return mark_safe('%s%s/%s/objects/%s/' % (self.model.site.root_url, self.model.model._meta.app_label, self.model.model._meta.module_name, iri_to_uri(self.pk())))
109
110     def fields(self):
111         """
112         Generator that yields EasyInstanceFields for each field in this
113         EasyInstance's model.
114         """
115         for f in self.model.model._meta.fields + self.model.model._meta.many_to_many:
116             yield EasyInstanceField(self.model, self, f)
117
118     def related_objects(self):
119         """
120         Generator that yields dictionaries of all models that have this
121         EasyInstance's model as a ForeignKey or ManyToManyField, along with
122         lists of related objects.
123         """
124         for rel_object in self.model.model._meta.get_all_related_objects() + self.model.model._meta.get_all_related_many_to_many_objects():
125             if rel_object.model not in self.model.model_list:
126                 continue # Skip models that aren't in the model_list
127             em = EasyModel(self.model.site, rel_object.model)
128             yield {
129                 'model': em,
130                 'related_field': rel_object.field.verbose_name,
131                 'object_list': [EasyInstance(em, i) for i in getattr(self.instance, rel_object.get_accessor_name()).all()],
132             }
133
134 class EasyInstanceField(object):
135     def __init__(self, easy_model, instance, field):
136         self.model, self.field, self.instance = easy_model, field, instance
137         self.raw_value = getattr(instance.instance, field.name)
138
139     def __repr__(self):
140         return smart_str(u'<EasyInstanceField for %s.%s>' % (self.model.model._meta.object_name, self.field.name))
141
142     def values(self):
143         """
144         Returns a list of values for this field for this instance. It's a list
145         so we can accomodate many-to-many fields.
146         """
147         # This import is deliberately inside the function because it causes
148         # some settings to be imported, and we don't want to do that at the
149         # module level.
150         if self.field.rel:
151             if isinstance(self.field.rel, models.ManyToOneRel):
152                 objs = getattr(self.instance.instance, self.field.name)
153             elif isinstance(self.field.rel, models.ManyToManyRel): # ManyToManyRel
154                 return list(getattr(self.instance.instance, self.field.name).all())
155         elif self.field.choices:
156             objs = dict(self.field.choices).get(self.raw_value, EMPTY_VALUE)
157         elif isinstance(self.field, models.DateField) or isinstance(self.field, models.TimeField):
158             if self.raw_value:
159                 date_format, datetime_format, time_format = get_date_formats()
160                 if isinstance(self.field, models.DateTimeField):
161                     objs = capfirst(dateformat.format(self.raw_value, datetime_format))
162                 elif isinstance(self.field, models.TimeField):
163                     objs = capfirst(dateformat.time_format(self.raw_value, time_format))
164                 else:
165                     objs = capfirst(dateformat.format(self.raw_value, date_format))
166             else:
167                 objs = EMPTY_VALUE
168         elif isinstance(self.field, models.BooleanField) or isinstance(self.field, models.NullBooleanField):
169             objs = {True: 'Yes', False: 'No', None: 'Unknown'}[self.raw_value]
170         else:
171             objs = self.raw_value
172         return [objs]
173
174     def urls(self):
175         "Returns a list of (value, URL) tuples."
176         # First, check the urls() method for each plugin.
177         plugin_urls = []
178         for plugin_name, plugin in self.model.model_databrowse().plugins.items():
179             urls = plugin.urls(plugin_name, self)
180             if urls is not None:
181                 #plugin_urls.append(urls)
182                 values = self.values()
183                 return zip(self.values(), urls)
184         if self.field.rel:
185             m = EasyModel(self.model.site, self.field.rel.to)
186             if self.field.rel.to in self.model.model_list:
187                 lst = []
188                 for value in self.values():
189                     url = mark_safe('%s%s/%s/objects/%s/' % (self.model.site.root_url, m.model._meta.app_label, m.model._meta.module_name, iri_to_uri(value._get_pk_val())))
190                     lst.append((smart_unicode(value), url))
191             else:
192                 lst = [(value, None) for value in self.values()]
193         elif self.field.choices:
194             lst = []
195             for value in self.values():
196                 url = mark_safe('%s%s/%s/fields/%s/%s/' % (self.model.site.root_url, self.model.model._meta.app_label, self.model.model._meta.module_name, self.field.name, iri_to_uri(self.raw_value)))
197                 lst.append((value, url))
198         elif isinstance(self.field, models.URLField):
199             val = self.values()[0]
200             lst = [(val, iri_to_uri(val))]
201         else:
202             lst = [(self.values()[0], None)]
203         return lst
204
205 class EasyQuerySet(QuerySet):
206     """
207     When creating (or cloning to) an `EasyQuerySet`, make sure to set the
208     `_easymodel` variable to the related `EasyModel`.
209     """
210     def iterator(self, *args, **kwargs):
211         for obj in super(EasyQuerySet, self).iterator(*args, **kwargs):
212             yield EasyInstance(self._easymodel, obj)
213
214     def _clone(self, *args, **kwargs):
215         c = super(EasyQuerySet, self)._clone(*args, **kwargs)
216         c._easymodel = self._easymodel
217         return c
Note: See TracBrowser for help on using the browser.