[Django]-Django: Example of generic relations using the contenttypes framework?

6👍

Your use case sounds very similar to the (now deprecated) Django comments framework. If you check out the models, you’ll see how to use a generic relation in BaseCommentAbstractModel–note that you need all three fields, a ForeignKey to ContentType, a field to hold the objects’ pks, and the GenericForeignKey field.

As for how to query for objects by GenericForeignKey, you can see some examples in the template tags in that project. See for example the get_query_set method in BaseCommentNode, which retrieves comments by querying on the content type and pk of the target object.

def get_query_set(self, context):
    ctype, object_pk = self.get_target_ctype_pk(context)
    if not object_pk:
        return self.comment_model.objects.none()

    qs = self.comment_model.objects.filter(
        content_type = ctype,
        object_pk    = smart_text(object_pk),
        site__pk     = settings.SITE_ID,
    )

3👍

I actually have a very similar situation on one of my projects, with various media types.

class TaggedItem(models.Model):
    tag = models.SlugField()
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    content_object = generic.GenericForeignKey('content_type', 'object_id') 

class ReviewedItem(models.Model):
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    content_object = generic.GenericForeignKey('content_type', 'object_id')
    review = models.ForeignKey("Review")

class CreativeWork(models.Model):
  #other fields 
  keywords = generic.GenericRelation("TaggedItem",null=True, blank=True, default=None)
  reviews = generic.GenericRelation("ReviewedItem",null=True, blank=True, default=None)

class MediaObject(CreativeWork):
  #fields
class VideoObject(MediaObject):
  #fields
class AudioObject(MediaObject):
  #fields

Every Video or Audio is a MediaObject, which is a CreativeWork.
CreativeWorks have a GenericRelation to tags and Reviews. So now anything can be tagged or reviewed.

All you need is for the ‘action’ to have a ForeignKey to ContentType.
Than add a GenericRelation to your model. I actually found the django.docs to be pretty helpful 🙂
But if not hope this helps.

1👍

Another option is Polymorphic Models. I won’t say it is the way you should go, but that it could perhaps be an option.

I am a fan of both generic foreign keys and Polymorphic Models. Polymorphic Models work best in those scenarios where there is a lot of similarity in the models.

Leave a comment