我有这个模型:
class Task(MPTTModel, TimeStampedModel, StartFinishModel):
name = models.CharField(max_length=256)
start_after_end = models.ManyToManyField('self',
related_name='s2e_relation',
blank=True)
#s2e means that task can't start before related tasks end
如何获取所有无法在此任务结束之前启动的任务以及所有必须在此任务开始之前终止的任务。
Let's say 1 -> 2 -> 3
我的ID为2
。我想找到3
,并找到另一个查询1
。
要找到3,我可以使用Task.objects.get(id = 2).start_after_end.all()
我如何找到1
?
更新1
实际上发现了更大的问题-如果我选择2 related to 1
-1会立即改变与1 is related to 2
的关系
答案 0 :(得分:2)
如果您与'self'
建立关系,则默认情况下Django会将关系设为对称。这意味着,如果对象a
具有朋友b
,则b
自动具有朋友a
。因此,这意味着此处的关系如下所示:
# symmetrical relation
1 <---> 2 <---> 3
因此,它意味着:
task1.start_after_end.all() # ==> [2]
task2.start_after_end.all() # ==> [1, 3]
task3.start_after_end.all() # ==> [2]
因此,1
和3
都将被视为Task2.start_after_end.all()
。您可能会不想要那样:您希望关系是非对称的。
因此,您应将字段编辑为:
class Task(MPTTModel, TimeStampedModel, StartFinishModel):
name = models.CharField(max_length=256)
start_after_end = models.ManyToManyField(
'self',
related_name='s2e_relation',
symmetrical=False,
blank=True
)
现在上面看起来像:
# asymmetrical relation
1 ---> 2 ---> 3
请注意,非对称关系是不是 反对称关系。仍然可以将task1
添加到start_after_end
的{{1}}中,但是如果您将task2
添加到{的{{1} {1}}。
所以现在完成了,这意味着对于task2
,我们将获得下一个任务:
start_after_end
我们用task1
得到了以前的版本:
some_task
例如:
my_task.start_after_end.all() # the next ones
然后,如果我们触发关系,我们得到:
related_name
答案 1 :(得分:0)
想法是使用related_name='s2e_relation'
中传递的ManyToManyField
您可以通过以下方式实现:
Task.objects.get(id=2).s2e_relation.all()