我正在搞乱Django试图了解更多信息,而且我对模型设计的理解遇到了一些障碍。我正在尝试创建一个类似于facebook“wall”的应用程序,但它纯粹是带有照片和视频的专辑,带有评论和投票。我的斗争是理解如何为可能有很多关系的项目设计关系。例如,您可以投票支持照片,视频,评论,专辑等。解决非特定项目的适当模型设计是什么?这是我迄今为止提出的结构。
self
答案 0 :(得分:1)
听起来你想要一个GenericForeignKey:
https://docs.djangoproject.com/en/1.11/ref/contrib/contenttypes/
ContentType模型允许您制作
它看起来像这样
from django.db import models
from django.contrib.auth.models import User
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
class Upvote(models.Model):
user = models.ForeignKey(User)
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey('content_type', 'object_id')
答案 1 :(得分:1)
您正在寻找GenericForeignKey,example:
class Vote(models.Model):
class Meta:
db_table = "votes"
index_together = [
["content_type", "object_id"],
]
# The following 3 fields represent the Comment or Post
# on which a vote has been cast
# See Generic Relations in Django's documentation
content_type = models.ForeignKey(ContentType, on_delete=models.PROTECT)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey('content_type', 'object_id')
voter = models.ForeignKey(User, on_delete=models.PROTECT)
type_of_vote = models.IntegerField(choices = (
(UPVOTE, 'Upvote'),
(DOWNVOTE, 'Downvote'),
(FLAG, 'Flag'),
))
submission_time = models.DateTimeField(auto_now_add=True)
此处,ContentType模型表示并存储有关项目中安装的模型的信息(相册,照片,视频...),并且每当安装新模型时,都会自动创建ContentType的新实例。
现在我们不需要将Foreign Key保存到我们想要跟踪的其他Django模型中。使用GenericRelations,我们现在可以将这些投票跟踪到我们想要的任何模型,而无需修改投票模型。
反向关系将是我们需要跟踪的模型的一部分。例如:
class Post:
...
...
votes = GenericRelation(Vote)
...
...
class Comment:
...
...
votes = GenericRelation(Vote)
...
...
现在,如果我们对现有的Post和Comment模型进行一些思考,我们会发现这两个模型应该以相同的方式表现出更多或更少的行为。例如,它们都可以被upvoted,downvoted,flagged,unflagged,因此它们应该提供接口来实现这一点。
因此,我们可以为它们创建一个基类作为Votable,并将常见的行为和属性推送到它。 Post和Comment将是具体的类,将继承自Votable。
class Votable(models.Model):
""" An object on which people would want to vote
Post and Comment are concrete classes
"""
class Meta:
abstract = True
votes = GenericRelation(Vote)
author = models.ForeignKey(User, on_delete=models.PROTECT)
# denormalization to save database queries
# flags = count of votes of type "Flag"
upvotes = models.IntegerField(default=0)
downvotes = models.IntegerField(default=0)
flags = models.IntegerField(default=0)
def upvote(self, user):
....
....
def downvote(self, user):
....
....
class Post(Votable):
# post specific implementation
...
...
class Comment(Votable):
# comment specific implementation
...
...