I have a task class, that can have sub-tasks, so it's a cyclic relationship. I'm passing it through a linker model/table like so:
class Task(models.Model):
title = models.CharField(max_length=100)
description = models.TextField(blank=True)
completed = models.BooleanField(default=False)
project = models.ForeignKey('Project', related_name="tasks")
dependancy = models.ManyToManyField('self', through='Dependancy', null=True,
blank=True, through_fields=('task', 'sub_task'), symmetrical=False)
def __str__(self):
return self.title
class Dependancy(models.Model):
task = models.ForeignKey(Task)
sub_task = models.ForeignKey(Task)
But I get this error:
ERRORS:
gantt_charts.dependency.sub_task: (fields.E303) Reverse query name for 'dependency.sub_task' clashes with field name 'Task.dependency'.
HINT: Rename field 'Task.dependency', or add/change a related_name argument to the definition for field 'dependency.sub_task'.
gantt_charts.dependency.sub_task: (fields.E304) Reverse accessor for 'dependency.sub_task' clashes with reverse accessor for 'dependency.task'.
HINT: Add or change a related_name argument to the definition for 'dependency.sub_task' or 'dependency.task'.
gantt_charts.dependency.task: (fields.E303) Reverse query name for 'dependency.task' clashes with field name 'Task.dependency'.
HINT: Rename field 'Task.dependency', or add/change a related_name argument to the definition for field 'dependency.task'.
gantt_charts.dependency.task: (fields.E304) Reverse accessor for 'dependency.task' clashes with reverse accessor for 'dependency.sub_task'.
HINT: Add or change a related_name argument to the definition for 'dependency.task' or 'dependency.sub_task'.
Obviously I need to set the related name on the Dependency.sub_task and Dependency.task field, and following the solution here is to name them something like task_task
and task_sub_task
, but that sounds wrong, unintuitive and confusing.
What would be a clear and concise name for them? It'd be easier if I wasn't getting confused over what related_names were, when using a linking table.
Given a Task
instance, how can you access all the Dependencies
that have that as their task
? Or their sub_task
? That's the purpose of related_name
—it provides the name for the attribute that Django will create on Task
to point to that group of things.
You're seeing that error because Django automatically uses the name <model>_set
, and since you have two ForeignKeys
pointing to the same model, the default name will conflict.
Now, it might be that you never need to directly access Dependencies
that way. If that's the case you can add related_name='+'
to both fields and the reverse attribute won't be created at all (and your errors will disappear).
If you do want to access them, the name is up to you. I prefer longer-but-more-descriptive names to make their purpose clear. I might model the problem like this:
class Task(models.Model):
subtasks = models.ManyToManyField('self',
through='Dependancy',
symmetrical=False,
through_fields=('supertask', 'subtask'),
related_name='supertasks')
class Dependancy(models.Model):
supertask = models.ForeignKey(Task, related_name='dependencies_as_supertask')
subtask = models.ForeignKey(Task, related_name='dependencies_as_subtask')
class Meta:
unique_together = ('supertask', 'subtask')
>>> task = Task.objects.get()
>>> # all the Tasks that are supertasks of this one
>>> task.supertasks
>>> # all the Tasks that are subtasks of this one
>>> task.subtasks
>>> # all the Dependencies with this Task as the supertask
>>> task.dependencies_as_supertask
>>> # all the Dependencies with this Task as the subtask
>>> task.dependencies_as_subtask
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With