Context Navigation


See http://www.djangoproject.com/documentation/models/generic_relations/.

Note: As of today, 13-DEC-06, this admonishment applies:

Generic relations: a "generic foreign key" feature is currently under development, 
but not yet completed. There is no support for it yet in the admin application, and 
it is probably unwise to attempt to use it in a production application.

--from http://code.djangoproject.com/

Also, I do not think that this is particularly good data modeling if you have a choice, but when migrating an application and dealing with legacy data as you go, it can be useful if it is not abused.

Model Source Code

classAttributeManager(models.Manager):
 defwith_attr(self, attr_name):
 return Attribute.objects.filter(name=attr_name)
 deftype_with_attr(self, type_name, attr_name):
 return Attribute.objects.filter(content_type__name=type_name, name=attr_name)
 deftype_with_attr_value(self, type_name, attr_name, value):
 return Attribute.objects.filter(content_type__name=type_name, name=attr_name, value=value)
 defobj_attr_list(self, obj):
 ctype = ContentType.objects.get_for_model(obj)
 return Attribute.objects.filter(content_type__pk=ctype.id, object_id=obj.id)
 defobj_attr_value(self, obj, attr_name):
 ctype = ContentType.objects.get_for_model(obj)
 try:
 av = Attribute.objects.get(name=attr_name, content_type__pk=ctype.id, object_id=obj.id)
 except Attribute.DoesNotExist:
 return None
 return av.value
classAttribute(models.Model):
 name = models.CharField(maxlength=25)
 content_type = models.ForeignKey(ContentType)
 object_id = models.PositiveIntegerField()
 value = models.CharField(maxlength=255)
 
 content_object = models.GenericForeignKey()
 objects = AttributeManager()
 classmeta:
 unique_together = (('name', 'content_type', 'object_id'),)
 
 def__str__(self):
 return "%s.%s.%s=%s" % (self.content_type.name, self.content_object, self.name, self.value,)

Sample API usage

This sample code assumes you added the above models to the sample found at http://www.djangoproject.com/documentation/models/generic_relations/.

>>> quartz = Mineral.objects.create(name="Quartz", hardness=10)
>>> emerald = Mineral.objects.create(name="Emerald", hardness=6)
>>> Attribute.objects.create(content_object=quartz, name='color', value='black')
<Attribute: mineral.Quartz.color=black>
>>> Attribute.objects.create(content_object=emerald, name='color', value='green')
<Attribute: mineral.Emerald.color=green>
>>> Attribute.objects.with_attr('color')
[<Attribute: mineral.Quartz.color=black>, <Attribute: mineral.Emerald.color=green>]
>>> Attribute.objects.type_with_attr('mineral', 'color')
[<Attribute: mineral.Quartz.color=black>, <Attribute: mineral.Emerald.color=green>]
>>> Attribute.objects.create(content_object=eggplant, name='color', value='purple')
<Attribute: vegetable.Eggplant.color=purple>
>>> Attribute.objects.with_attr('color')
[<Attribute: mineral.Quartz.color=black>, <Attribute: mineral.Emerald.color=green>, <Attribute: vegetable.Eggplant.color=
purple>]
>>> Attribute.objects.type_with_attr('mineral', 'color')
[<Attribute: mineral.Quartz.color=black>, <Attribute: mineral.Emerald.color=green>]
>>> Attribute.objects.type_with_attr_value('mineral', 'color', 'green')
[<Attribute: mineral.Emerald.color=green>]
>>> Attribute.objects.type_with_attr_value('mineral', 'color', 'red')
[]
>>> Attribute.objects.obj_attr_list(quartz)
[<Attribute: mineral.Quartz.color=black>]
>>> Attribute.objects.obj_attr_value(quartz, 'color')
'black'
Last modified 15 years ago Last modified on Jun 25, 2010, 3:01:51 PM
Note: See TracWiki for help on using the wiki.
Back to Top