Django:使用contenttypes框架的泛型关系的例子?

时间:2013-06-06 03:05:39

标签: python django django-models django-contenttypes generic-foreign-key

我多次仔细研究了关于contenttypes框架的Django文档,而我根本不理解它在我的项目中实现泛型关系。我已经找到了有关此事的在线示例或教程,但我找不到一个。叫我笨,但我需要一些帮助(请不要简单地链接到文档)。基于在线资源的缺乏,我相信如果你用一个详尽的例子回答这个问题,你的回答可能是迄今为止关于django泛型关系的最有用的例子(奖金!)。

所以,我的问题是:有人可以展示一个简单的模型示例,也可能有几行代码显示如何与泛型模型的实例进行交互?


作为灵感,我相信这是一个非常常见的情况:

网站的媒体项目大致相同,但略有不同。例如,假设有图像和视频项目,用户可以“喜欢”项目或“注释”项目。喜欢和评论应该被视为相同,无论它们是张贴在图像还是视频项目上。因此,如果有用于查看用户相册中的图片或视频的ItemView,则可以进行以下类型的调用:mediaitem.comments.all()len(mediaitem.likes.all())comment.user_who_commented,而无需了解它是哪种媒体项目(图像或视频)。

我相信你需要六个模型

  • 摘要MediaItem
  • 两种不同类型的媒体项:ImageItemVideoItem
  • 摘要MediaItemActions
  • 可以针对媒体项目执行的两种不同类型的操作:LikeComment

如果您知道如何使用这个Django功能,请向我们展示一个完整的示例!我觉得这将是一个非常强大的工具,我很想在我的应用程序中使用它。越明确越好。

3 个答案:

答案 0 :(得分:6)

您的用例听起来与(现已弃用)Django comments framework非常相似。如果您查看models,则会在BaseCommentAbstractModel中看到如何使用通用关系 - 请注意,您需要所有三个字段,ForeignKeyContentType,用于保存对象“pkGenericForeignKey字段的字段。

至于如何通过GenericForeignKey查询对象,您可以在该项目的template tags中看到一些示例。请参阅get_query_set中的BaseCommentNode方法,该方法通过查询目标对象的内容类型和pk来检索注释。

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,
    )

答案 1 :(得分:3)

我的一个项目实际上有类似的情况,有各种媒体类型。

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

每个视频或音频都是MediaObject,它是CreativeWork。 CreativeWorks对标签和评论有GenericRelation。所以现在任何东西都可以被标记或评论。

您所需要的只是“行动”'将ForeignKey设置为ContentType。 然后将GenericRelation添加到模型中。我实际上发现django.docs非常有用:) 但如果不希望这会有所帮助。

答案 2 :(得分:1)

另一个选项是Polymorphic Models。我不会说这是你应该去的方式,但它可能是一个选择。

我是通用外键和多态模型的粉丝。多态模型在模型中存在很多相似性的情况下效果最佳。

相关问题