如何使用直通表并指向 self 使用 ManyToManyField 设置 related_name

Pur*_*ret 5 django django-models

我有一个任务类,可以有子任务,所以这是一个循环关系。我通过链接器模型/表传递它,如下所示:

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)
Run Code Online (Sandbox Code Playgroud)

但我收到此错误:

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'.
Run Code Online (Sandbox Code Playgroud)

显然,我需要在 Dependency.sub_task 和 Dependency.task 字段上设置相关名称,并且按照此处的解决方案将它们命名为task_taskand 之类的名称task_sub_task,但这听起来是错误的,不直观且令人困惑。

什么是他们的清晰简洁的名称?如果我在使用链接表时不会对相关名称是什么感到困惑,那会更容易。

Kev*_*nry 6

给定一个Task实例,您如何访问所有Dependencies将其作为其的task?还是他们的sub_task?这就是 \xe2\x80\x94 的目的,related_name它提供了 Django 将创建的属性的名称,以Task指向该组事物。

\n\n

您看到该错误是因为 Django 自动使用 name <model>_set,并且由于您有两个ForeignKeys指向同一模型,因此默认名称将发生冲突。

\n\n

现在,您可能永远不需要以Dependencies这种方式直接访问。如果是这种情况,您可以添加related_name='+'到这两个字段,并且完全不会创建反向属性(并且您的错误将消失)。

\n\n

如果您确实想访问它们,名称由您决定。我更喜欢更长但更具描述性的名称,以明确其目的。我可能会像这样对问题进行建模:

\n\n
class Task(models.Model): \n    subtasks = models.ManyToManyField('self', \n                                      through='Dependancy',\n                                      symmetrical=False,\n                                      through_fields=('supertask', 'subtask'),\n                                      related_name='supertasks')\n\nclass Dependancy(models.Model):\n    supertask = models.ForeignKey(Task, related_name='dependencies_as_supertask')\n    subtask = models.ForeignKey(Task, related_name='dependencies_as_subtask')\n\n    class Meta:\n        unique_together = ('supertask', 'subtask')\n\n\n>>> task = Task.objects.get()\n\n>>> # all the Tasks that are supertasks of this one\n>>> task.supertasks\n\n>>> # all the Tasks that are subtasks of this one\n>>> task.subtasks\n\n>>> # all the Dependencies with this Task as the supertask\n>>> task.dependencies_as_supertask\n\n>>> # all the Dependencies with this Task as the subtask\n>>> task.dependencies_as_subtask\n
Run Code Online (Sandbox Code Playgroud)\n