2 These classes are light wrappers around Django's database API that provide
3 convenience functionality and permalink functions for the databrowse app.
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
14 EMPTY_VALUE
= '(None)'
16 class EasyModel(object):
17 def __init__(self
, site
, 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
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
]
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
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
):
51 f
= self
.model
._meta
.get_field(name
)
52 except models
.FieldDoesNotExist
:
54 return EasyField(self
, f
)
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
64 return smart_str(u
'<EasyField for %s.%s>' % (self
.model
.model
._meta
.object_name
, self
.field
.name
))
67 for value
, label
in self
.field
.choices
:
68 yield EasyChoice(self
.model
, self
, value
, label
)
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
))
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
82 return smart_str(u
'<EasyChoice for %s.%s>' % (self
.model
.model
._meta
.object_name
, self
.field
.name
))
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
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
)
97 return val
[:30] + u
'...'
101 return self
.__unicode
__().encode('utf-8')
104 return self
.instance
._get
_pk
_val
()
107 return '%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()))
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
)
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
)
139 return smart_str(u
'<EasyInstanceField for %s.%s>' % (self
.model
.model
._meta
.object_name
, self
.field
.name
))
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
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
):
158 date_format
, datetime_format
, time_format
= get_date_formats()
159 if isinstance(self
.field
, models
.DateTimeField
):
160 objs
= capfirst(dateformat
.format(self
.raw_value
, datetime_format
))
161 elif isinstance(self
.field
, models
.TimeField
):
162 objs
= capfirst(dateformat
.time_format(self
.raw_value
, time_format
))
164 objs
= capfirst(dateformat
.format(self
.raw_value
, date_format
))
167 elif isinstance(self
.field
, models
.BooleanField
) or isinstance(self
.field
, models
.NullBooleanField
):
168 objs
= {True: 'Yes', False: 'No', None: 'Unknown'}[self
.raw_value
]
170 objs
= self
.raw_value
174 "Returns a list of (value, URL) tuples."
175 # First, check the urls() method for each plugin.
177 for plugin_name
, plugin
in self
.model
.model_databrowse().plugins
.items():
178 urls
= plugin
.urls(plugin_name
, self
)
180 #plugin_urls.append(urls)
181 values
= self
.values()
182 return zip(self
.values(), urls
)
184 m
= EasyModel(self
.model
.site
, self
.field
.rel
.to
)
185 if self
.field
.rel
.to
in self
.model
.model_list
:
187 for value
in self
.values():
188 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
())))
189 lst
.append((smart_unicode(value
), url
))
191 lst
= [(value
, None) for value
in self
.values()]
192 elif self
.field
.choices
:
194 for value
in self
.values():
195 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
)))
196 lst
.append((value
, url
))
197 elif isinstance(self
.field
, models
.URLField
):
198 val
= self
.values()[0]
199 lst
= [(val
, iri_to_uri(val
))]
201 lst
= [(self
.values()[0], None)]
204 class EasyQuerySet(QuerySet
):
206 When creating (or cloning to) an `EasyQuerySet`, make sure to set the
207 `_easymodel` variable to the related `EasyModel`.
209 def iterator(self
, *args
, **kwargs
):
210 for obj
in super(EasyQuerySet
, self
).iterator(*args
, **kwargs
):
211 yield EasyInstance(self
._easymodel
, obj
)
213 def _clone(self
, *args
, **kwargs
):
214 c
= super(EasyQuerySet
, self
)._clone
(*args
, **kwargs
)
215 c
._easymodel
= self
._easymodel