App Engine Python SDK version 1.7.4 (2)
[gae.git] / python / lib / django_1_4 / django / contrib / databrowse / datastructures.py
blob9a4ba17e19f8202f3854a31281c1462759e12fa5
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 """
6 from django.db import models
7 from django.utils import formats
8 from django.utils.text import capfirst
9 from django.utils.encoding import smart_unicode, smart_str, iri_to_uri
10 from django.utils.safestring import mark_safe
11 from django.db.models.query import QuerySet
13 EMPTY_VALUE = '(None)'
14 DISPLAY_SIZE = 100
16 class EasyModel(object):
17 def __init__(self, site, model):
18 self.site = site
19 self.model = model
20 self.model_list = site.registry.keys()
21 self.verbose_name = model._meta.verbose_name
22 self.verbose_name_plural = model._meta.verbose_name_plural
24 def __repr__(self):
25 return '<EasyModel for %s>' % smart_str(self.model._meta.object_name)
27 def model_databrowse(self):
28 "Returns the ModelDatabrowse class for this model."
29 return self.site.registry[self.model]
31 def url(self):
32 return mark_safe('%s%s/%s/' % (self.site.root_url, self.model._meta.app_label, self.model._meta.module_name))
34 def objects(self, **kwargs):
35 return self.get_query_set().filter(**kwargs)
37 def get_query_set(self):
38 easy_qs = self.model._default_manager.get_query_set()._clone(klass=EasyQuerySet)
39 easy_qs._easymodel = self
40 return easy_qs
42 def object_by_pk(self, pk):
43 return EasyInstance(self, self.model._default_manager.get(pk=pk))
45 def sample_objects(self):
46 for obj in self.model._default_manager.all()[:3]:
47 yield EasyInstance(self, obj)
49 def field(self, name):
50 try:
51 f = self.model._meta.get_field(name)
52 except models.FieldDoesNotExist:
53 return None
54 return EasyField(self, f)
56 def fields(self):
57 return [EasyField(self, f) for f in (self.model._meta.fields + self.model._meta.many_to_many)]
59 class EasyField(object):
60 def __init__(self, easy_model, field):
61 self.model, self.field = easy_model, field
63 def __repr__(self):
64 return smart_str(u'<EasyField for %s.%s>' % (self.model.model._meta.object_name, self.field.name))
66 def choices(self):
67 for value, label in self.field.choices:
68 yield EasyChoice(self.model, self, value, label)
70 def url(self):
71 if self.field.choices:
72 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))
73 elif self.field.rel:
74 return mark_safe('%s%s/%s/' % (self.model.site.root_url, self.model.model._meta.app_label, self.model.model._meta.module_name))
76 class EasyChoice(object):
77 def __init__(self, easy_model, field, value, label):
78 self.model, self.field = easy_model, field
79 self.value, self.label = value, label
81 def __repr__(self):
82 return smart_str(u'<EasyChoice for %s.%s>' % (self.model.model._meta.object_name, self.field.name))
84 def url(self):
85 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 class EasyInstance(object):
88 def __init__(self, easy_model, instance):
89 self.model, self.instance = easy_model, instance
91 def __repr__(self):
92 return smart_str(u'<EasyInstance for %s (%s)>' % (self.model.model._meta.object_name, self.instance._get_pk_val()))
94 def __unicode__(self):
95 val = smart_unicode(self.instance)
96 if len(val) > DISPLAY_SIZE:
97 return val[:DISPLAY_SIZE] + u'...'
98 return val
100 def __str__(self):
101 return self.__unicode__().encode('utf-8')
103 def pk(self):
104 return self.instance._get_pk_val()
106 def url(self):
107 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 def fields(self):
111 Generator that yields EasyInstanceFields for each field in this
112 EasyInstance's model.
114 for f in self.model.model._meta.fields + self.model.model._meta.many_to_many:
115 yield EasyInstanceField(self.model, self, f)
117 def related_objects(self):
119 Generator that yields dictionaries of all models that have this
120 EasyInstance's model as a ForeignKey or ManyToManyField, along with
121 lists of related objects.
123 for rel_object in self.model.model._meta.get_all_related_objects() + self.model.model._meta.get_all_related_many_to_many_objects():
124 if rel_object.model not in self.model.model_list:
125 continue # Skip models that aren't in the model_list
126 em = EasyModel(self.model.site, rel_object.model)
127 yield {
128 'model': em,
129 'related_field': rel_object.field.verbose_name,
130 'object_list': [EasyInstance(em, i) for i in getattr(self.instance, rel_object.get_accessor_name()).all()],
133 class EasyInstanceField(object):
134 def __init__(self, easy_model, instance, field):
135 self.model, self.field, self.instance = easy_model, field, instance
136 self.raw_value = getattr(instance.instance, field.name)
138 def __repr__(self):
139 return smart_str(u'<EasyInstanceField for %s.%s>' % (self.model.model._meta.object_name, self.field.name))
141 def values(self):
143 Returns a list of values for this field for this instance. It's a list
144 so we can accomodate many-to-many fields.
146 # This import is deliberately inside the function because it causes
147 # some settings to be imported, and we don't want to do that at the
148 # module level.
149 if self.field.rel:
150 if isinstance(self.field.rel, models.ManyToOneRel):
151 objs = getattr(self.instance.instance, self.field.name)
152 elif isinstance(self.field.rel, models.ManyToManyRel): # ManyToManyRel
153 return list(getattr(self.instance.instance, self.field.name).all())
154 elif self.field.choices:
155 objs = dict(self.field.choices).get(self.raw_value, EMPTY_VALUE)
156 elif isinstance(self.field, models.DateField) or isinstance(self.field, models.TimeField):
157 if self.raw_value:
158 if isinstance(self.field, models.DateTimeField):
159 objs = capfirst(formats.date_format(self.raw_value, 'DATETIME_FORMAT'))
160 elif isinstance(self.field, models.TimeField):
161 objs = capfirst(formats.time_format(self.raw_value, 'TIME_FORMAT'))
162 else:
163 objs = capfirst(formats.date_format(self.raw_value, 'DATE_FORMAT'))
164 else:
165 objs = EMPTY_VALUE
166 elif isinstance(self.field, models.BooleanField) or isinstance(self.field, models.NullBooleanField):
167 objs = {True: 'Yes', False: 'No', None: 'Unknown'}[self.raw_value]
168 else:
169 objs = self.raw_value
170 return [objs]
172 def urls(self):
173 "Returns a list of (value, URL) tuples."
174 # First, check the urls() method for each plugin.
175 plugin_urls = []
176 for plugin_name, plugin in self.model.model_databrowse().plugins.items():
177 urls = plugin.urls(plugin_name, self)
178 if urls is not None:
179 #plugin_urls.append(urls)
180 values = self.values()
181 return zip(self.values(), urls)
182 if self.field.rel:
183 m = EasyModel(self.model.site, self.field.rel.to)
184 if self.field.rel.to in self.model.model_list:
185 lst = []
186 for value in self.values():
187 if value is None:
188 continue
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
205 class EasyQuerySet(QuerySet):
207 When creating (or cloning to) an `EasyQuerySet`, make sure to set the
208 `_easymodel` variable to the related `EasyModel`.
210 def iterator(self, *args, **kwargs):
211 for obj in super(EasyQuerySet, self).iterator(*args, **kwargs):
212 yield EasyInstance(self._easymodel, obj)
214 def _clone(self, *args, **kwargs):
215 c = super(EasyQuerySet, self)._clone(*args, **kwargs)
216 c._easymodel = self._easymodel
217 return c