Changeset 6900
- Timestamp:
- 12/09/07 01:12:07 (9 months ago)
- Files:
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
django/trunk/django/contrib/contenttypes/generic.py
r5967 r6900 17 17 fields. 18 18 """ 19 19 20 20 def __init__(self, ct_field="content_type", fk_field="object_id"): 21 21 self.ct_field = ct_field 22 22 self.fk_field = fk_field 23 23 24 24 def contribute_to_class(self, cls, name): 25 # Make sure the fields exist (these raise FieldDoesNotExist, 25 # Make sure the fields exist (these raise FieldDoesNotExist, 26 26 # which is a fine error to raise here) 27 27 self.name = name 28 28 self.model = cls 29 29 self.cache_attr = "_%s_cache" % name 30 30 31 31 # For some reason I don't totally understand, using weakrefs here doesn't work. 32 32 dispatcher.connect(self.instance_pre_init, signal=signals.pre_init, sender=cls, weak=False) … … 36 36 37 37 def instance_pre_init(self, signal, sender, args, kwargs): 38 # Handle initalizing an object with the generic FK instaed of 39 # content-type/object-id fields. 38 # Handle initalizing an object with the generic FK instaed of 39 # content-type/object-id fields. 40 40 if self.name in kwargs: 41 41 value = kwargs.pop(self.name) 42 42 kwargs[self.ct_field] = self.get_content_type(value) 43 43 kwargs[self.fk_field] = value._get_pk_val() 44 44 45 45 def get_content_type(self, obj): 46 46 # Convenience function using get_model avoids a circular import when using this model 47 47 ContentType = get_model("contenttypes", "contenttype") 48 48 return ContentType.objects.get_for_model(obj) 49 49 50 50 def __get__(self, instance, instance_type=None): 51 51 if instance is None: … … 78 78 setattr(instance, self.fk_field, fk) 79 79 setattr(instance, self.cache_attr, value) 80 80 81 81 class GenericRelation(RelatedField, Field): 82 82 """Provides an accessor to generic related objects (i.e. comments)""" … … 84 84 def __init__(self, to, **kwargs): 85 85 kwargs['verbose_name'] = kwargs.get('verbose_name', None) 86 kwargs['rel'] = GenericRel(to, 86 kwargs['rel'] = GenericRel(to, 87 87 related_name=kwargs.pop('related_name', None), 88 88 limit_choices_to=kwargs.pop('limit_choices_to', None), 89 89 symmetrical=kwargs.pop('symmetrical', True)) 90 90 91 91 # Override content-type/object-id field names on the related class 92 92 self.object_id_field_name = kwargs.pop("object_id_field", "object_id") 93 self.content_type_field_name = kwargs.pop("content_type_field", "content_type") 94 93 self.content_type_field_name = kwargs.pop("content_type_field", "content_type") 94 95 95 kwargs['blank'] = True 96 96 kwargs['editable'] = False … … 117 117 def m2m_column_name(self): 118 118 return self.object_id_field_name 119 119 120 120 def m2m_reverse_name(self): 121 return self. object_id_field_name121 return self.model._meta.pk.column 122 122 123 123 def contribute_to_class(self, cls, name): … … 132 132 def contribute_to_related_class(self, cls, related): 133 133 pass 134 134 135 135 def set_attributes_from_rel(self): 136 136 pass … … 138 138 def get_internal_type(self): 139 139 return "ManyToManyField" 140 140 141 141 class ReverseGenericRelatedObjectsDescriptor(object): 142 142 """ … … 194 194 Manager) and adds behavior for generic related objects. 195 195 """ 196 196 197 197 class GenericRelatedObjectManager(superclass): 198 198 def __init__(self, model=None, core_filters=None, instance=None, symmetrical=None, 199 199 join_table=None, source_col_name=None, target_col_name=None, content_type=None, 200 200 content_type_field_name=None, object_id_field_name=None): 201 201 202 202 super(GenericRelatedObjectManager, self).__init__() 203 203 self.core_filters = core_filters or {} … … 213 213 self.object_id_field_name = object_id_field_name 214 214 self.pk_val = self.instance._get_pk_val() 215 215 216 216 def get_query_set(self): 217 217 query = { 218 '%s__pk' % self.content_type_field_name : self.content_type.id, 218 '%s__pk' % self.content_type_field_name : self.content_type.id, 219 219 '%s__exact' % self.object_id_field_name : self.pk_val, 220 220 } django/trunk/tests/modeltests/generic_relations/models.py
r5876 r6900 19 19 content_type = models.ForeignKey(ContentType) 20 20 object_id = models.PositiveIntegerField() 21 21 22 22 content_object = generic.GenericForeignKey() 23 23 24 24 class Meta: 25 25 ordering = ["tag"] 26 26 27 27 def __unicode__(self): 28 28 return self.tag … … 31 31 common_name = models.CharField(max_length=150) 32 32 latin_name = models.CharField(max_length=150) 33 33 34 34 tags = generic.GenericRelation(TaggedItem) 35 35 36 36 def __unicode__(self): 37 37 return self.common_name 38 38 39 39 class Vegetable(models.Model): 40 40 name = models.CharField(max_length=150) 41 41 is_yucky = models.BooleanField(default=True) 42 42 43 43 tags = generic.GenericRelation(TaggedItem) 44 44 45 45 def __unicode__(self): 46 46 return self.name 47 47 48 48 class Mineral(models.Model): 49 49 name = models.CharField(max_length=150) 50 50 hardness = models.PositiveSmallIntegerField() 51 51 52 52 # note the lack of an explicit GenericRelation here... 53 53 54 54 def __unicode__(self): 55 55 return self.name 56 56 57 57 __test__ = {'API_TESTS':""" 58 58 # Create the world in 7 lines of code... … … 118 118 [(u'clearish', <ContentType: mineral>, 1), (u'fatty', <ContentType: vegetable>, 2), (u'salty', <ContentType: vegetable>, 2), (u'shiny', <ContentType: animal>, 2)] 119 119 120 # If Generic Relation is not explicitly defined, any related objects 120 # If Generic Relation is not explicitly defined, any related objects 121 121 # remain after deletion of the source object. 122 122 >>> quartz.delete() … … 124 124 [(u'clearish', <ContentType: mineral>, 1), (u'fatty', <ContentType: vegetable>, 2), (u'salty', <ContentType: vegetable>, 2), (u'shiny', <ContentType: animal>, 2)] 125 125 126 # If you delete a tag, the objects using the tag are unaffected 126 # If you delete a tag, the objects using the tag are unaffected 127 127 # (other than losing a tag) 128 128 >>> tag = TaggedItem.objects.get(id=1) … … 133 133 [(u'clearish', <ContentType: mineral>, 1), (u'salty', <ContentType: vegetable>, 2), (u'shiny', <ContentType: animal>, 2)] 134 134 135 >>> ctype = ContentType.objects.get_for_model(lion) 136 >>> Animal.objects.filter(tags__content_type=ctype) 137 [<Animal: Platypus>] 138 135 139 """}
