Django

Code

Changeset 7228

Show
Ignore:
Timestamp:
03/11/08 19:09:13 (9 months ago)
Author:
jacob
Message:

Fixed #5570: generic foreign keys no longer do multiple lookups on the content type. This uses the new ctype caching bit added in [7216].

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • django/trunk/django/contrib/contenttypes/generic.py

    r6900 r7228  
    4040        if self.name in kwargs: 
    4141            value = kwargs.pop(self.name) 
    42             kwargs[self.ct_field] = self.get_content_type(value) 
     42            kwargs[self.ct_field] = self.get_content_type(obj=value) 
    4343            kwargs[self.fk_field] = value._get_pk_val() 
    4444 
    45     def get_content_type(self, obj): 
     45    def get_content_type(self, obj=None, id=None): 
    4646        # Convenience function using get_model avoids a circular import when using this model 
    4747        ContentType = get_model("contenttypes", "contenttype") 
    48         return ContentType.objects.get_for_model(obj) 
     48        if obj: 
     49            return ContentType.objects.get_for_model(obj) 
     50        elif id: 
     51            return ContentType.objects.get_for_id(id) 
     52        else: 
     53            # This should never happen. I love comments like this, don't you? 
     54            raise Exception("Impossible arguments to GFK.get_content_type!") 
    4955 
    5056    def __get__(self, instance, instance_type=None): 
     
    5662        except AttributeError: 
    5763            rel_obj = None 
    58             ct = getattr(instance, self.ct_field) 
    59             if ct: 
     64             
     65            # Make sure to use ContentType.objects.get_for_id() to ensure that 
     66            # lookups are cached (see ticket #5570). This takes more code than 
     67            # the naive ``getattr(instance, self.ct_field)``, but has better  
     68            # performance when dealing with GFKs in loops and such. 
     69            f = self.model._meta.get_field(self.ct_field) 
     70            ct_id = getattr(instance, f.get_attname(), None) 
     71            if ct_id: 
     72                ct = self.get_content_type(id=ct_id) 
    6073                try: 
    6174                    rel_obj = ct.get_object_for_this_type(pk=getattr(instance, self.fk_field)) 
     
    7285        fk = None 
    7386        if value is not None: 
    74             ct = self.get_content_type(value) 
     87            ct = self.get_content_type(obj=value) 
    7588            fk = value._get_pk_val() 
    7689