~ubuntu-branches/ubuntu/precise/python-django/precise-proposed

« back to all changes in this revision

Viewing changes to django/contrib/contenttypes/generic.py

  • Committer: Package Import Robot
  • Author(s): Andres Rodriguez, Julian Edwards
  • Date: 2012-11-20 16:00:41 UTC
  • Revision ID: package-import@ubuntu.com-20121120160041-140ztibl9h0omz79
Tags: 1.3.1-4ubuntu1.5
[ Julian Edwards ]
* debian/patches:
  - genericipaddressfield.diff: Backport GenericIPAddressField
    from 1.4 (LP: #1081391)
  - prefetch_related.diff: Backport prefetch_related from 1.4 (LP: #1081388)
  - bug15496-base64-multipart-fix.diff: Include fix for upstream bug #15496
    which makes 'Content-Transfer-Encoding: base64: work for multipart
    messages. (LP: #1081392)

Show diffs side-by-side

added added

removed removed

Lines of Context:
2
2
Classes allowing "generic" relations through ContentType and object-id fields.
3
3
"""
4
4
 
 
5
from collections import defaultdict
 
6
from operator import attrgetter
 
7
 
5
8
from django.core.exceptions import ObjectDoesNotExist
6
9
from django.db import connection
7
10
from django.db.models import signals
61
64
            # This should never happen. I love comments like this, don't you?
62
65
            raise Exception("Impossible arguments to GFK.get_content_type!")
63
66
 
 
67
    def get_prefetch_query_set(self, instances):
 
68
        # For efficiency, group the instances by content type and then do one
 
69
        # query per model
 
70
        fk_dict = defaultdict(set)
 
71
        # We need one instance for each group in order to get the right db:
 
72
        instance_dict = {}
 
73
        ct_attname = self.model._meta.get_field(self.ct_field).get_attname()
 
74
        for instance in instances:
 
75
            # We avoid looking for values if either ct_id or fkey value is None
 
76
            ct_id = getattr(instance, ct_attname)
 
77
            if ct_id is not None:
 
78
                fk_val = getattr(instance, self.fk_field)
 
79
                if fk_val is not None:
 
80
                    fk_dict[ct_id].add(fk_val)
 
81
                    instance_dict[ct_id] = instance
 
82
 
 
83
        ret_val = []
 
84
        for ct_id, fkeys in fk_dict.items():
 
85
            instance = instance_dict[ct_id]
 
86
            ct = self.get_content_type(id=ct_id, using=instance._state.db)
 
87
            ret_val.extend(ct.get_all_objects_for_this_type(pk__in=fkeys))
 
88
 
64
89
    def __get__(self, instance, instance_type=None):
65
90
        if instance is None:
66
91
            return self
226
251
            target_col_name = qn(self.field.m2m_reverse_name()),
227
252
            content_type = ContentType.objects.db_manager(instance._state.db).get_for_model(instance),
228
253
            content_type_field_name = self.field.content_type_field_name,
229
 
            object_id_field_name = self.field.object_id_field_name
 
254
            object_id_field_name = self.field.object_id_field_name,
 
255
            prefetch_cache_name = self.field.attname,
230
256
        )
231
257
 
232
258
        return manager
249
275
    class GenericRelatedObjectManager(superclass):
250
276
        def __init__(self, model=None, core_filters=None, instance=None, symmetrical=None,
251
277
                     join_table=None, source_col_name=None, target_col_name=None, content_type=None,
252
 
                     content_type_field_name=None, object_id_field_name=None):
 
278
                     content_type_field_name=None, object_id_field_name=None,
 
279
                     prefetch_cache_name=None):
253
280
 
254
281
            super(GenericRelatedObjectManager, self).__init__()
255
282
            self.core_filters = core_filters or {}
263
290
            self.target_col_name = target_col_name
264
291
            self.content_type_field_name = content_type_field_name
265
292
            self.object_id_field_name = object_id_field_name
 
293
            self.prefetch_cache_name = prefetch_cache_name
266
294
            self.pk_val = self.instance._get_pk_val()
267
295
 
268
296
        def get_query_set(self):
269
 
            db = self._db or router.db_for_read(self.model, instance=self.instance)
 
297
            try:
 
298
                return self.instance._prefetched_objects_cache[self.prefetch_cache_name]
 
299
            except (AttributeError, KeyError):
 
300
                db = self._db or router.db_for_read(self.model, instance=self.instance)
 
301
                query = {
 
302
                    '%s__pk' % self.content_type_field_name : self.content_type.id,
 
303
                    '%s__exact' % self.object_id_field_name : self.pk_val,
 
304
                }
 
305
                return superclass.get_query_set(self).using(db).filter(**query)
 
306
 
 
307
        def get_prefetch_query_set(self, instances):
 
308
            db = self._db or router.db_for_read(self.model, instance=instances[0])
270
309
            query = {
271
 
                '%s__pk' % self.content_type_field_name : self.content_type.id,
272
 
                '%s__exact' % self.object_id_field_name : self.pk_val,
273
 
            }
274
 
            return superclass.get_query_set(self).using(db).filter(**query)
 
310
                '%s__pk' % self.content_type_field_name: self.content_type.id,
 
311
                '%s__in' % self.object_id_field_name:
 
312
                    set(obj._get_pk_val() for obj in instances)
 
313
                }
 
314
            qs = super(GenericRelatedObjectManager, self).get_query_set().using(db).filter(**query)
 
315
            return (qs,
 
316
                    attrgetter(self.object_id_field_name),
 
317
                    lambda obj: obj._get_pk_val(),
 
318
                    False,
 
319
                    self.prefetch_cache_name)
275
320
 
276
321
        def add(self, *objs):
277
322
            for obj in objs: