Django关系名称冲突 - 抽象模型与另一个模型有多种关系

时间:2016-03-23 15:21:39

标签: django database-design

我的申请包含三个ModelsUsersTopicsResponses

每个Response可以在Topic或另一个Response处理,但大致相同。为了不复制代码,我认为最好制作一个抽象模型ResponseResponseResponseTopicResponse继承。

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有两个名为affirmers的冲突关系,另两个名为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(就像你没有指定它一样)以及关系的名称。

1 个答案:

答案 0 :(得分: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)