Django

Code

root/django/trunk/django/db/models/base.py

Revision 10955, 29.0 kB (checked in by russellm, 4 weeks ago)

Fixed #11194 -- Corrected loading of Proxy models from fixtures (and, by extension, save_base(raw=True) for Proxy models).

  • Property svn:eol-style set to native
Line 
1 import copy
2 import types
3 import sys
4 import os
5 from itertools import izip
6 try:
7     set
8 except NameError:
9     from sets import Set as set     # Python 2.3 fallback.
10
11 import django.db.models.manager     # Imported to register signal handler.
12 from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned, FieldError
13 from django.db.models.fields import AutoField, FieldDoesNotExist
14 from django.db.models.fields.related import OneToOneRel, ManyToOneRel, OneToOneField
15 from django.db.models.query import delete_objects, Q
16 from django.db.models.query_utils import CollectedObjects, DeferredAttribute
17 from django.db.models.options import Options
18 from django.db import connection, transaction, DatabaseError
19 from django.db.models import signals
20 from django.db.models.loading import register_models, get_model
21 from django.utils.functional import curry
22 from django.utils.encoding import smart_str, force_unicode, smart_unicode
23 from django.conf import settings
24
25
26 class ModelBase(type):
27     """
28     Metaclass for all models.
29     """
30     def __new__(cls, name, bases, attrs):
31         super_new = super(ModelBase, cls).__new__
32         parents = [b for b in bases if isinstance(b, ModelBase)]
33         if not parents:
34             # If this isn't a subclass of Model, don't do anything special.
35             return super_new(cls, name, bases, attrs)
36
37         # Create the class.
38         module = attrs.pop('__module__')
39         new_class = super_new(cls, name, bases, {'__module__': module})
40         attr_meta = attrs.pop('Meta', None)
41         abstract = getattr(attr_meta, 'abstract', False)
42         if not attr_meta:
43             meta = getattr(new_class, 'Meta', None)
44         else:
45             meta = attr_meta
46         base_meta = getattr(new_class, '_meta', None)
47
48         if getattr(meta, 'app_label', None) is None:
49             # Figure out the app_label by looking one level up.
50             # For 'django.contrib.sites.models', this would be 'sites'.
51             model_module = sys.modules[new_class.__module__]
52             kwargs = {"app_label": model_module.__name__.split('.')[-2]}
53         else:
54             kwargs = {}
55
56         new_class.add_to_class('_meta', Options(meta, **kwargs))
57         if not abstract:
58             new_class.add_to_class('DoesNotExist',
59                     subclass_exception('DoesNotExist', ObjectDoesNotExist, module))
60             new_class.add_to_class('MultipleObjectsReturned',
61                     subclass_exception('MultipleObjectsReturned', MultipleObjectsReturned, module))
62             if base_meta and not base_meta.abstract:
63                 # Non-abstract child classes inherit some attributes from their
64                 # non-abstract parent (unless an ABC comes before it in the
65                 # method resolution order).
66                 if not hasattr(meta, 'ordering'):
67                     new_class._meta.ordering = base_meta.ordering
68                 if not hasattr(meta, 'get_latest_by'):
69                     new_class._meta.get_latest_by = base_meta.get_latest_by
70
71         is_proxy = new_class._meta.proxy
72
73         if getattr(new_class, '_default_manager', None):
74             if not is_proxy:
75                 # Multi-table inheritance doesn't inherit default manager from
76                 # parents.
77                 new_class._default_manager = None
78                 new_class._base_manager = None
79             else:
80                 # Proxy classes do inherit parent's default manager, if none is
81                 # set explicitly.
82                 new_class._default_manager = new_class._default_manager._copy_to_model(new_class)
83                 new_class._base_manager = new_class._base_manager._copy_to_model(new_class)
84
85         # Bail out early if we have already created this class.
86         m = get_model(new_class._meta.app_label, name, False)
87         if m is not None:
88             return m
89
90         # Add all attributes to the class.
91         for obj_name, obj in attrs.items():
92             new_class.add_to_class(obj_name, obj)
93
94         # All the fields of any type declared on this model
95         new_fields = new_class._meta.local_fields + \
96                      new_class._meta.local_many_to_many + \
97                      new_class._meta.virtual_fields
98         field_names = set([f.name for f in new_fields])
99
100         # Basic setup for proxy models.
101         if is_proxy:
102             base = None
103             for parent in [cls for cls in parents if hasattr(cls, '_meta')]:
104                 if parent._meta.abstract:
105                     if parent._meta.fields:
106                         raise TypeError("Abstract base class containing model fields not permitted for proxy model '%s'." % name)
107                     else:
108                         continue
109                 if base is not None:
110                     raise TypeError("Proxy model '%s' has more than one non-abstract model base class." % name)
111                 else:
112                     base = parent
113             if base is None:
114                     raise TypeError("Proxy model '%s' has no non-abstract model base class." % name)
115             if (new_class._meta.local_fields or
116                     new_class._meta.local_many_to_many):
117                 raise FieldError("Proxy model '%s' contains model fields."
118                         % name)
119             while base._meta.proxy:
120                 base = base._meta.proxy_for_model
121             new_class._meta.setup_proxy(base)
122
123         # Do the appropriate setup for any model parents.
124         o2o_map = dict([(f.rel.to, f) for f in new_class._meta.local_fields
125                 if isinstance(f, OneToOneField)])
126
127         for base in parents:
128             original_base = base
129             if not hasattr(base, '_meta'):
130                 # Things without _meta aren't functional models, so they're
131                 # uninteresting parents.
132                 continue
133
134             parent_fields = base._meta.local_fields + base._meta.local_many_to_many
135             # Check for clashes between locally declared fields and those
136             # on the base classes (we cannot handle shadowed fields at the
137             # moment).
138             for field in parent_fields:
139                 if field.name in field_names:
140                     raise FieldError('Local field %r in class %r clashes '
141                                      'with field of similar name from '
142                                      'base class %r' %
143                                         (field.name, name, base.__name__))
144             if not base._meta.abstract:
145                 # Concrete classes...
146                 while base._meta.proxy:
147                     # Skip over a proxy class to the "real" base it proxies.
148                     base = base._meta.proxy_for_model
149                 if base in o2o_map:
150                     field = o2o_map[base]
151                 elif not is_proxy:
152                     attr_name = '%s_ptr' % base._meta.module_name
153                     field = OneToOneField(base, name=attr_name,
154                             auto_created=True, parent_link=True)
155                     new_class.add_to_class(attr_name, field)
156                 else:
157                     field = None
158                 new_class._meta.parents[base] = field
159             else:
160                 # .. and abstract ones.
161                 for field in parent_fields:
162                     new_class.add_to_class(field.name, copy.deepcopy(field))
163
164                 # Pass any non-abstract parent classes onto child.
165                 new_class._meta.parents.update(base._meta.parents)
166
167             # Inherit managers from the abstract base classes.
168             new_class.copy_managers(base._meta.abstract_managers)
169
170             # Proxy models inherit the non-abstract managers from their base,
171             # unless they have redefined any of them.
172             if is_proxy:
173                 new_class.copy_managers(original_base._meta.concrete_managers)
174
175             # Inherit virtual fields (like GenericForeignKey) from the parent
176             # class
177             for field in base._meta.virtual_fields:
178                 if base._meta.abstract and field.name in field_names:
179                     raise FieldError('Local field %r in class %r clashes '\
180                                      'with field of similar name from '\
181                                      'abstract base class %r' % \
182                                         (field.name, name, base.__name__))
183                 new_class.add_to_class(field.name, copy.deepcopy(field))
184
185         if abstract:
186             # Abstract base models can't be instantiated and don't appear in
187             # the list of models for an app. We do the final setup for them a
188             # little differently from normal models.
189             attr_meta.abstract = False
190             new_class.Meta = attr_meta
191             return new_class
192
193         new_class._prepare()
194         register_models(new_class._meta.app_label, new_class)
195
196         # Because of the way imports happen (recursively), we may or may not be
197         # the first time this model tries to register with the framework. There
198         # should only be one class for each model, so we always return the
199         # registered version.
200         return get_model(new_class._meta.app_label, name, False)
201
202     def copy_managers(cls, base_managers):
203         # This is in-place sorting of an Options attribute, but that's fine.
204         base_managers.sort()
205         for _, mgr_name, manager in base_managers:
206             val = getattr(cls, mgr_name, None)
207             if not val or val is manager:
208                 new_manager = manager._copy_to_model(cls)
209                 cls.add_to_class(mgr_name, new_manager)
210
211     def add_to_class(cls, name, value):
212         if hasattr(value, 'contribute_to_class'):
213             value.contribute_to_class(cls, name)
214         else:
215             setattr(cls, name, value)
216
217     def _prepare(cls):
218         """
219         Creates some methods once self._meta has been populated.
220         """
221         opts = cls._meta
222         opts._prepare(cls)
223
224         if opts.order_with_respect_to:
225             cls.get_next_in_order = curry(cls._get_next_or_previous_in_order, is_next=True)
226             cls.get_previous_in_order = curry(cls._get_next_or_previous_in_order, is_next=False)
227             setattr(opts.order_with_respect_to.rel.to, 'get_%s_order' % cls.__name__.lower(), curry(method_get_order, cls))
228             setattr(opts.order_with_respect_to.rel.to, 'set_%s_order' % cls.__name__.lower(), curry(method_set_order, cls))
229
230         # Give the class a docstring -- its definition.
231         if cls.__doc__ is None:
232             cls.__doc__ = "%s(%s)" % (cls.__name__, ", ".join([f.attname for f in opts.fields]))
233
234         if hasattr(cls, 'get_absolute_url'):
235             cls.get_absolute_url = curry(get_absolute_url, opts, cls.get_absolute_url)
236
237         signals.class_prepared.send(sender=cls)
238
239
240 class Model(object):
241     __metaclass__ = ModelBase
242     _deferred = False
243
244     def __init__(self, *args, **kwargs):
245         signals.pre_init.send(sender=self.__class__, args=args, kwargs=kwargs)
246
247         # There is a rather weird disparity here; if kwargs, it's set, then args
248         # overrides it. It should be one or the other; don't duplicate the work
249         # The reason for the kwargs check is that standard iterator passes in by
250         # args, and instantiation for iteration is 33% faster.
251         args_len = len(args)
252         if args_len > len(self._meta.fields):
253             # Daft, but matches old exception sans the err msg.
254             raise IndexError("Number of args exceeds number of fields")
255
256         fields_iter = iter(self._meta.fields)
257         if not kwargs:
258             # The ordering of the izip calls matter - izip throws StopIteration
259             # when an iter throws it. So if the first iter throws it, the second
260             # is *not* consumed. We rely on this, so don't change the order
261             # without changing the logic.
262             for val, field in izip(args, fields_iter):
263                 setattr(self, field.attname, val)
264         else:
265             # Slower, kwargs-ready version.
266             for val, field in izip(args, fields_iter):
267                 setattr(self, field.attname, val)
268                 kwargs.pop(field.name, None)
269                 # Maintain compatibility with existing calls.
270                 if isinstance(field.rel, ManyToOneRel):
271                     kwargs.pop(field.attname, None)
272
273         # Now we're left with the unprocessed fields that *must* come from
274         # keywords, or default.
275
276         for field in fields_iter:
277             is_related_object = False
278             # This slightly odd construct is so that we can access any
279             # data-descriptor object (DeferredAttribute) without triggering its
280             # __get__ method.
281             if (field.attname not in kwargs and
282                     isinstance(self.__class__.__dict__.get(field.attname), DeferredAttribute)):
283                 # This field will be populated on request.
284                 continue
285             if kwargs:
286                 if isinstance(field.rel, ManyToOneRel):
287                     try:
288                         # Assume object instance was passed in.
289                         rel_obj = kwargs.pop(field.name)
290                         is_related_object = True
291                     except KeyError:
292                         try:
293                             # Object instance wasn't passed in -- must be an ID.
294                             val = kwargs.pop(field.attname)
295                         except KeyError:
296                             val = field.get_default()
297                     else:
298                         # Object instance was passed in. Special case: You can
299                         # pass in "None" for related objects if it's allowed.
300                         if rel_obj is None and field.null:
301                             val = None
302                 else:
303                     val = kwargs.pop(field.attname, field.get_default())
304             else:
305                 val = field.get_default()
306             if is_related_object:
307                 # If we are passed a related instance, set it using the
308                 # field.name instead of field.attname (e.g. "user" instead of
309                 # "user_id") so that the object gets properly cached (and type
310                 # checked) by the RelatedObjectDescriptor.
311                 setattr(self, field.name, rel_obj)
312             else:
313                 setattr(self, field.attname, val)
314
315         if kwargs:
316             for prop in kwargs.keys():
317                 try:
318                     if isinstance(getattr(self.__class__, prop), property):
319                         setattr(self, prop, kwargs.pop(prop))
320                 except AttributeError:
321                     pass
322             if kwargs:
323                 raise TypeError, "'%s' is an invalid keyword argument for this function" % kwargs.keys()[0]
324         signals.post_init.send(sender=self.__class__, instance=self)
325
326     def __repr__(self):
327         try:
328             u = unicode(self)
329         except (UnicodeEncodeError, UnicodeDecodeError):
330             u = '[Bad Unicode data]'
331         return smart_str(u'<%s: %s>' % (self.__class__.__name__, u))
332
333     def __str__(self):
334         if hasattr(self, '__unicode__'):
335             return force_unicode(self).encode('utf-8')
336         return '%s object' % self.__class__.__name__
337
338     def __eq__(self, other):
339         return isinstance(other, self.__class__) and self._get_pk_val() == other._get_pk_val()
340
341     def __ne__(self, other):
342         return not self.__eq__(other)
343
344     def __hash__(self):
345         return hash(self._get_pk_val())
346
347     def __reduce__(self):
348         """
349         Provide pickling support. Normally, this just dispatches to Python's
350         standard handling. However, for models with deferred field loading, we
351         need to do things manually, as they're dynamically created classes and
352         only module-level classes can be pickled by the default path.
353         """
354         data = self.__dict__
355         if not self._deferred:
356             return (self.__class__, (), data)
357         defers = []
358         pk_val = None
359         for field in self._meta.fields:
360             if isinstance(self.__class__.__dict__.get(field.attname),
361                     DeferredAttribute):
362                 defers.append(field.attname)
363                 if pk_val is None:
364                     # The pk_val and model values are the same for all
365                     # DeferredAttribute classes, so we only need to do this
366                     # once.
367                     obj = self.__class__.__dict__[field.attname]
368                     model = obj.model_ref()
369         return (model_unpickle, (model, defers), data)
370
371     def _get_pk_val(self, meta=None):
372         if not meta:
373             meta = self._meta
374         return getattr(self, meta.pk.attname)
375
376     def _set_pk_val(self, value):
377         return setattr(self, self._meta.pk.attname, value)
378
379     pk = property(_get_pk_val, _set_pk_val)
380
381     def serializable_value(self, field_name):
382         """
383         Returns the value of the field name for this instance. If the field is
384         a foreign key, returns the id value, instead of the object. If there's
385         no Field object with this name on the model, the model attribute's
386         value is returned directly.
387
388         Used to serialize a field's value (in the serializer, or form output,
389         for example). Normally, you would just access the attribute directly
390         and not use this method.
391         """
392         try:
393             field = self._meta.get_field_by_name(field_name)[0]
394         except FieldDoesNotExist:
395             return getattr(self, field_name)
396         return getattr(self, field.attname)
397
398     def save(self, force_insert=False, force_update=False):
399         """
400         Saves the current instance. Override this in a subclass if you want to
401         control the saving process.
402
403         The 'force_insert' and 'force_update' parameters can be used to insist
404         that the "save" must be an SQL insert or update (or equivalent for
405         non-SQL backends), respectively. Normally, they should not be set.
406         """
407         if force_insert and force_update:
408             raise ValueError("Cannot force both insert and updating in "
409                     "model saving.")
410         self.save_base(force_insert=force_insert, force_update=force_update)
411
412     save.alters_data = True
413
414     def save_base(self, raw=False, cls=None, origin=None,
415             force_insert=False, force_update=False):
416         """
417         Does the heavy-lifting involved in saving. Subclasses shouldn't need to
418         override this method. It's separate from save() in order to hide the
419         need for overrides of save() to pass around internal-only parameters
420         ('raw', 'cls', and 'origin').
421         """
422         assert not (force_insert and force_update)
423         if cls is None:
424             cls = self.__class__
425             meta = cls._meta
426             if not meta.proxy:
427                 origin = cls
428         else:
429             meta = cls._meta
430
431         if origin:
432             signals.pre_save.send(sender=origin, instance=self, raw=raw)
433
434         # If we are in a raw save, save the object exactly as presented.
435         # That means that we don't try to be smart about saving attributes
436         # that might have come from the parent class - we just save the
437         # attributes we have been given to the class we have been given.
438         # We also go through this process to defer the save of proxy objects
439         # to their actual underlying model.
440         if not raw or meta.proxy:
441             if meta.proxy:
442                 org = cls
443             else:
444                 org = None
445             for parent, field in meta.parents.items():
446                 # At this point, parent's primary key field may be unknown
447                 # (for example, from administration form which doesn't fill
448                 # this field). If so, fill it.
449                 if field and getattr(self, parent._meta.pk.attname) is None and getattr(self, field.attname) is not None:
450                     setattr(self, parent._meta.pk.attname, getattr(self, field.attname))
451
452                 self.save_base(cls=parent, origin=org)
453
454                 if field:
455                     setattr(self, field.attname, self._get_pk_val(parent._meta))
456             if meta.proxy:
457                 return
458
459         if not meta.proxy:
460             non_pks = [f for f in meta.local_fields if not f.primary_key]
461
462             # First, try an UPDATE. If that doesn't update anything, do an INSERT.
463             pk_val = self._get_pk_val(meta)
464             pk_set = pk_val is not None
465             record_exists = True
466             manager = cls._base_manager
467             if pk_set:
468                 # Determine whether a record with the primary key already exists.
469                 if (force_update or (not force_insert and
470                         manager.filter(pk=pk_val).extra(select={'a': 1}).values('a').order_by())):
471                     # It does already exist, so do an UPDATE.
472                     if force_update or non_pks:
473                         values = [(f, None, (raw and getattr(self, f.attname) or f.pre_save(self, False))) for f in non_pks]
474                         rows = manager.filter(pk=pk_val)._update(values)
475                         if force_update and not rows:
476                             raise DatabaseError("Forced update did not affect any rows.")
477                 else:
478                     record_exists = False
479             if not pk_set or not record_exists:
480                 if not pk_set:
481                     if force_update:
482                         raise ValueError("Cannot force an update in save() with no primary key.")
483                     values = [(f, f.get_db_prep_save(raw and getattr(self, f.attname) or f.pre_save(self, True))) for f in meta.local_fields if not isinstance(f, AutoField)]
484                 else:
485                     values = [(f, f.get_db_prep_save(raw and getattr(self, f.attname) or f.pre_save(self, True))) for f in meta.local_fields]
486
487                 if meta.order_with_respect_to:
488                     field = meta.order_with_respect_to
489                     values.append((meta.get_field_by_name('_order')[0], manager.filter(**{field.name: getattr(self, field.attname)}).count()))
490                 record_exists = False
491
492                 update_pk = bool(meta.has_auto_field and not pk_set)
493                 if values:
494                     # Create a new record.
495                     result = manager._insert(values, return_id=update_pk)
496                 else:
497                     # Create a new record with defaults for everything.
498                     result = manager._insert([(meta.pk, connection.ops.pk_default_value())], return_id=update_pk, raw_values=True)
499
500                 if update_pk:
501                     setattr(self, meta.pk.attname, result)
502             transaction.commit_unless_managed()
503
504         if origin:
505             signals.post_save.send(sender=origin, instance=self,
506                 created=(not record_exists), raw=raw)
507
508     save_base.alters_data = True
509
510     def _collect_sub_objects(self, seen_objs, parent=None, nullable=False):
511         """
512         Recursively populates seen_objs with all objects related to this
513         object.
514
515         When done, seen_objs.items() will be in the format:
516             [(model_class, {pk_val: obj, pk_val: obj, ...}),
517              (model_class, {pk_val: obj, pk_val: obj, ...}), ...]
518         """
519         pk_val = self._get_pk_val()
520         if seen_objs.add(self.__class__, pk_val, self, parent, nullable):
521             return
522
523         for related in self._meta.get_all_related_objects():
524             rel_opts_name = related.get_accessor_name()
525             if isinstance(related.field.rel, OneToOneRel):
526                 try:
527                     sub_obj = getattr(self, rel_opts_name)
528                 except ObjectDoesNotExist:
529                     pass
530                 else:
531                     sub_obj._collect_sub_objects(seen_objs, self.__class__, related.field.null)
532             else:
533                 # To make sure we can access all elements, we can't use the
534                 # normal manager on the related object. So we work directly
535                 # with the descriptor object.
536                 for cls in self.__class__.mro():
537                     if rel_opts_name in cls.__dict__:
538                         rel_descriptor = cls.__dict__[rel_opts_name]
539                         break
540                 else:
541                     raise AssertionError("Should never get here.")
542                 delete_qs = rel_descriptor.delete_manager(self).all()
543                 for sub_obj in delete_qs:
544                     sub_obj._collect_sub_objects(seen_objs, self.__class__, related.field.null)
545
546         # Handle any ancestors (for the model-inheritance case). We do this by
547         # traversing to the most remote parent classes -- those with no parents
548         # themselves -- and then adding those instances to the collection. That
549         # will include all the child instances down to "self".
550         parent_stack = [p for p in self._meta.parents.values() if p is not None]
551         while parent_stack:
552             link = parent_stack.pop()
553             parent_obj = getattr(self, link.name)
554             if parent_obj._meta.parents:
555                 parent_stack.extend(parent_obj._meta.parents.values())
556                 continue
557             # At this point, parent_obj is base class (no ancestor models). So
558             # delete it and all its descendents.
559             parent_obj._collect_sub_objects(seen_objs)
560
561     def delete(self):
562         assert self._get_pk_val() is not None, "%s object can't be deleted because its %s attribute is set to None." % (self._meta.object_name, self._meta.pk.attname)
563
564         # Find all the objects than need to be deleted.
565         seen_objs = CollectedObjects()
566         self._collect_sub_objects(seen_objs)
567
568         # Actually delete the objects.
569         delete_objects(seen_objs)
570
571     delete.alters_data = True
572
573     def _get_FIELD_display(self, field):
574         value = getattr(self, field.attname)
575         return force_unicode(dict(field.flatchoices).get(value, value), strings_only=True)
576
577     def _get_next_or_previous_by_FIELD(self, field, is_next, **kwargs):
578         op = is_next and 'gt' or 'lt'
579         order = not is_next and '-' or ''
580         param = smart_str(getattr(self, field.attname))
581         q = Q(**{'%s__%s' % (field.name, op): param})
582         q = q|Q(**{field.name: param, 'pk__%s' % op: self.pk})
583         qs = self.__class__._default_manager.filter(**kwargs).filter(q).order_by('%s%s' % (order, field.name), '%spk' % order)
584         try:
585             return qs[0]
586         except IndexError:
587             raise self.DoesNotExist, "%s matching query does not exist." % self.__class__._meta.object_name
588
589     def _get_next_or_previous_in_order(self, is_next):
590         cachename = "__%s_order_cache" % is_next
591         if not hasattr(self, cachename):
592             qn = connection.ops.quote_name
593             op = is_next and '>' or '<'
594             order = not is_next and '-_order' or '_order'
595             order_field = self._meta.order_with_respect_to
596             # FIXME: When querysets support nested queries, this can be turned
597             # into a pure queryset operation.
598             where = ['%s %s (SELECT %s FROM %s WHERE %s=%%s)' % \
599                 (qn('_order'), op, qn('_order'),
600                 qn(self._meta.db_table), qn(self._meta.pk.column))]
601             params = [self.pk]
602             obj = self._default_manager.filter(**{order_field.name: getattr(self, order_field.attname)}).extra(where=where, params=params).order_by(order)[:1].get()
603             setattr(self, cachename, obj)
604         return getattr(self, cachename)
605
606     def prepare_database_save(self, unused):
607         return self.pk
608
609
610 ############################################
611 # HELPER FUNCTIONS (CURRIED MODEL METHODS) #
612 ############################################
613
614 # ORDERING METHODS #########################
615
616 def method_set_order(ordered_obj, self, id_list):
617     rel_val = getattr(self, ordered_obj._meta.order_with_respect_to.rel.field_name)
618     order_name = ordered_obj._meta.order_with_respect_to.name
619     # FIXME: It would be nice if there was an "update many" version of update
620     # for situations like this.
621     for i, j in enumerate(id_list):
622         ordered_obj.objects.filter(**{'pk': j, order_name: rel_val}).update(_order=i)
623     transaction.commit_unless_managed()
624
625
626 def method_get_order(ordered_obj, self):
627     rel_val = getattr(self, ordered_obj._meta.order_with_respect_to.rel.field_name)
628     order_name = ordered_obj._meta.order_with_respect_to.name
629     pk_name = ordered_obj._meta.pk.name
630     return [r[pk_name] for r in
631             ordered_obj.objects.filter(**{order_name: rel_val}).values(pk_name)]
632
633
634 ##############################################
635 # HELPER FUNCTIONS (CURRIED MODEL FUNCTIONS) #
636 ##############################################
637
638 def get_absolute_url(opts, func, self, *args, **kwargs):
639     return settings.ABSOLUTE_URL_OVERRIDES.get('%s.%s' % (opts.app_label, opts.module_name), func)(self, *args, **kwargs)
640
641
642 ########
643 # MISC #
644 ########
645
646 class Empty(object):
647     pass
648
649 def model_unpickle(model, attrs):
650     """
651     Used to unpickle Model subclasses with deferred fields.
652     """
653     from django.db.models.query_utils import deferred_class_factory
654     cls = deferred_class_factory(model, attrs)
655     return cls.__new__(cls)
656 model_unpickle.__safe_for_unpickle__ = True
657
658 if sys.version_info < (2, 5):
659     # Prior to Python 2.5, Exception was an old-style class
660     def subclass_exception(name, parent, unused):
661         return types.ClassType(name, (parent,), {})
662 else:
663     def subclass_exception(name, parent, module):
664         return type(name, (parent,), {'__module__': module})
Note: See TracBrowser for help on using the browser.