Django模型设计的“墙”型应用程序

时间:2017-07-22 03:16:29

标签: django django-models

我正在搞乱Django试图了解更多信息,而且我对模型设计的理解遇到了一些障碍。我正在尝试创建一个类似于facebook“wall”的应用程序,但它纯粹是带有照片和视频的专辑,带有评论和投票。我的斗争是理解如何为可能有很多关系的项目设计关系。例如,您可以投票支持照片,视频,评论,专辑等。解决非特定项目的适当模型设计是什么?这是我迄今为止提出的结构。

self

2 个答案:

答案 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
    ...
    ...

Source

more info