Reputation: 21496
My application consists of three Models
: Users
, Topics
, and Responses
.
Each Response
may either be addressed at a Topic
, or at another Response
, but are largely identical. In the interest of not duplicating code, I thought it best to make an abstract model, Response
, which ResponseResponse
and TopicResponse
inherit from.
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)
The issue with this is that the User
has two conflicting relationships called affirmers
and two called rejectors
.
If I don't give them related names, then instead TopicResponse
and ResponseResponse
each have three conflicting relationships, all of them called TopicResponse
or ResponseResponse
, respectively, (one for agreers
, one for affirms
, one for rejects
).
An example error message is:
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'.
If I leave off the related_name
argument, I get error messages like this:
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'.
What can I do to fix all of these conflicts? I need to somehow have the related_name
dynamically generated with the name of the of the concrete instance of the Model (like it is if you don't specify it) plus the name of the relationship.
Upvotes: 1
Views: 114
Reputation: 11439
You have to make the related name unique. As stated in the docs you can add %(class)s
or %(app_label)s
. These are then replaced by the child class values:
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)
Upvotes: 2