2017-07-22 54 views
0

我搞砸Django试图学习更多,我打了一点与模型设计的理解障碍。我试图创建一个类似Facebook的“墙”的应用程序,但它纯粹是带有照片和视频的专辑,带有评论和投票。我的努力是理解如何设计可能有很多关系的项目的关系。作为一个例子,你可以上传照片,视频,评论,专辑等等。处理非特定项目的适当模型设计是什么?这是我迄今为止提出的结构。“墙”型应用程序Django模型设计

Album --primary 
--id 
--datetime 
--created by 
--title 
--photo(s) 
--comment(s) 
--+1(s) 

photo 
--id 
--foreignkey album 
--datetime 
--uploaded by 
--caption 
--comment(s) 
--path 
--+1(s) 

video 
--id 
--foreignkey album 
--datetime 
--caption 
--comment(s) 
--path 
--+1(s) 

comments 
--id 
--user 
--datetime 
+1(s) 


+1s 
--id 
--user 

回答

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

你”重新寻找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的新实例。

现在我们不需要保留我们想跟踪的其他Django模型的外键。使用GenericRelations,我们现在可以跟踪我们想要的任何模型的投票,而无需修改投票模型。

反向关系将成为我们需要跟踪的模型的一部分。例如:

class Post: 
    ... 
    ... 
    votes = GenericRelation(Vote) 
    ... 
    ... 

class Comment: 
    ... 
    ... 
    votes = GenericRelation(Vote) 
    ... 
    ... 

现在,如果我们把多花点心思我们现有的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

+0

了很多很好的信息和参考这里。如果我需要分两次进行分类,会怎么样?喜欢,一张照片可以评论和投票? – Jaberwocky

+0

你可以有像上面这样的抽象类,例如:VotableMixin,CommentableMixin。然后:class Photo(VotableMixin,CommentableMixin) – ziiiro

+0

@ziiro你有没有另一个好的学习资源呢? – Jaberwocky

相关问题