2016-03-23 29 views
1

我的應用程序由三個ModelsUsers,TopicsResponses組成。Django關係名稱衝突 - 抽象模型與另一個模型有多種關係

每個Response可以在Topic,或在另一個Response尋址,但大部分是相同的。爲了不重複代碼,我認爲最好做一個抽象模型,Response,其中ResponseResponseTopicResponse繼承自。

from django.contrib.auth.models import User 
from django.db.models   import (CASCADE, CharField, DateTimeField, 
             ForeignKey, ManyToManyField, Model, 
             TextField) 

class Topic(Model): 
    name = CharField(max_length = 100) 

class Response(Model): 
    body = TextField() 
    topics = ManyToManyField(Topic) 
    agreers = ManyToManyField(User) 

    proposal = TextField() 
    affirms = ManyToManyField(User, related_name = 'affirmers') 
    rejects = ManyToManyField(User, related_name = 'rejectors') 

    class Meta: 
     abstract = True 

class TopicResponse(Response): 
    responseTo = ForeignKey(Topic, on_delete = CASCADE) 

class ResponseResponse(Response): 
    responseTo = ForeignKey(Response, on_delete = CASCADE) 

這樣做的問題是,User有兩個相互矛盾的關係稱爲和兩個叫rejectors

如果我不給他們相關的名字,然後代替TopicResponseResponseResponse各自具有三個相互矛盾的關係,所有的人都稱爲TopicResponseResponseResponse,分別是(一個用於agreers,一個用於affirms,一個用於rejects)。

一個例子錯誤消息是:

app.TopicResponse.rejects: (fields.E305) Reverse query name for 'TopicResponse.rejects' clashes with reverse query name for 'ResponseResponse.rejects'. 
     HINT: Add or change a related_name argument to the definition for 'TopicResponse.rejects' or 'ResponseResponse.rejects'. 

如果我離開關related_name說法,我得到的錯誤信息是這樣的:

app.ResponseResponse.rejects: (fields.E304) Reverse accessor for 'ResponseResponse.rejects' clashes with reverse accessor for 'ResponseResponse.affirms'. 
     HINT: Add or change a related_name argument to the definition for 'ResponseResponse.rejects' or 'ResponseResponse.affirms'. 

我能做些什麼來解決所有這些衝突?我需要以某種方式動態生成related_name,其中包含模型的具體實例的名稱(就像沒有指定它的名稱一樣)以及關係的名稱。

回答

2

您必須使相關名稱唯一。如docs中所述,您可以添加%(class)s%(app_label)s。這些然後被子類值取代:

class Topic(Model): 
    name = CharField(max_length = 100) 

    class Response(Model): 
     body = TextField() 
     topics = ManyToManyField(Topic) 
     agreers = ManyToManyField(User) 

     proposal = TextField() 
     affirms = ManyToManyField(User, related_name = '%(app_label)s_%(class)saffirmers') 
     rejects = ManyToManyField(User, related_name = '%(app_label)s_%(class)srejectors') 

     class Meta: 
      abstract = True 

    class TopicResponse(Response): 
     responseTo = ForeignKey(Topic, on_delete = CASCADE) 

    class ResponseResponse(Response): 
     responseTo = ForeignKey(Response, on_delete = CASCADE) 
+1

太棒了!謝謝!這看起來應該起作用 - 一旦我今晚驗證了它,我會回來接受你的答案。 – ArtOfWarfare