我多次仔细研究了关于contenttypes框架的Django文档,而我根本不理解它在我的项目中实现泛型关系。我已经找到了有关此事的在线示例或教程,但我找不到一个。叫我笨,但我需要一些帮助(请不要简单地链接到文档)。基于在线资源的缺乏,我相信如果你用一个详尽的例子回答这个问题,你的回答可能是迄今为止关于django泛型关系的最有用的例子(奖金!)。
所以,我的问题是:有人可以展示一个简单的模型示例,也可能有几行代码显示如何与泛型模型的实例进行交互?
作为灵感,我相信这是一个非常常见的情况:
网站的媒体项目大致相同,但略有不同。例如,假设有图像和视频项目,用户可以“喜欢”项目或“注释”项目。喜欢和评论应该被视为相同,无论它们是张贴在图像还是视频项目上。因此,如果有用于查看用户相册中的图片或视频的ItemView,则可以进行以下类型的调用:mediaitem.comments.all()
或len(mediaitem.likes.all())
或comment.user_who_commented
,而无需了解它是哪种媒体项目(图像或视频)。
我相信你需要六个模型:
MediaItem
类ImageItem
和VideoItem
MediaItemActions
类Like
和Comment
如果您知道如何使用这个Django功能,请向我们展示一个完整的示例!我觉得这将是一个非常强大的工具,我很想在我的应用程序中使用它。越明确越好。
答案 0 :(得分:6)
您的用例听起来与(现已弃用)Django comments framework非常相似。如果您查看models,则会在BaseCommentAbstractModel
中看到如何使用通用关系 - 请注意,您需要所有三个字段,ForeignKey
到ContentType
,用于保存对象“pk
和GenericForeignKey
字段的字段。
至于如何通过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。我不会说这是你应该去的方式,但它可能是一个选择。
我是通用外键和多态模型的粉丝。多态模型在模型中存在很多相似性的情况下效果最佳。