2017-07-22 16 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