Dear people trying to help others,
亲爱的人们试图帮助他人,
I am trying to figure out how to get Django to do a join for me without writing custom SQL.
我试图弄清楚如何让Django为我做一个连接,而无需编写自定义SQL。
Let's say I have the following models
假设我有以下型号
class Parent(models.Model):
name = models.CharField()
children = models.ManyToManyField(Child, through="Parent_Child", related_name="parents")
class Parent_Child(models.Model):
parent = models.ForeignKey(Parent, related_name='attached_children')
child = models.ForeignKey(Child, related_name='attached_parents')
class Child(models.Model):
name = models.CharField()
toys = models.ManyToManyField(Toy, hrough="Child_Toy", related_name="toy_owners")
class Child_Toy(models.Model):
child = models.ForeignKey(Child, related_name='attached_toys')
toy = models.ForeignKey(Toy, related_name='toy_owner')
class Toy(models.Model):
name = models.CharField
A parent can have multiple children. A child can have multiple parents. A child can own multiple toys. Toys can be owned by multiple children.
父母可以有多个孩子。一个孩子可以有多个父母。孩子可以拥有多个玩具。玩具可以由多个孩子拥有。
I want to get a list of all toys owned by a Parent's Children.
我想获得父母子女拥有的所有玩具清单。
So, I can do things like: parent.children.all()
and child.toys.all()
所以,我可以这样做:parent.children.all()和child.toys.all()
what I want to do is something like parent.children.toys.all()
When I try to do this I get: AttributeError: 'ManyRelatedManager' object has no attribute 'toys'
. I do understand the error - parent.children
returns multiple records. This is expected. What I can't figure out is how to give Django the hint that I want it to add an additional join to its query.
我想做的是像parent.children.toys.all()当我尝试这样做时,我得到:AttributeError:'ManyRelatedManager'对象没有属性'玩具'。我理解错误 - parent.children返回多条记录。这是预料之中的。我无法弄清楚的是如何给Django提示我希望它为其查询添加一个额外的连接。
Is there a way I can do this join within Django or do I need to go to custom SQL in order to do this?
有没有办法可以在Django中进行此连接,还是我需要转到自定义SQL才能执行此操作?
Please Note: The above is just meant to illustrate my issue, the actual models that I am using aren't that relevant. My issue is really trying to figure out how to join through multiple M2M relationships in Django without having to resort to SQL.
请注意:以上只是为了说明我的问题,我使用的实际模型并不相关。我的问题是试图弄清楚如何在Django中通过多个M2M关系加入,而不必诉诸SQL。
I appreciate your help in advance. Thanks!
我提前感谢您的帮助。谢谢!
2 个解决方案
#1
7
Simply write something like:
只需写下以下内容:
Toy.objects.filter(toy_owners__parents=parent)
#2
2
If you don't store extra information in the intermediate tables Parent_Child
and Child_Toy
you can just leave them out - Django will create them automatically for you. So a simplified setup would look like this:
如果你不在中间表Parent_Child和Child_Toy中存储额外的信息,你可以将它们遗漏--Django将自动为你创建它们。所以简化的设置看起来像这样:
class Parent(models.Model):
name = models.CharField(max_length=80)
children = models.ManyToManyField('Child', related_name="parent")
class Child(models.Model):
name = models.CharField(max_length=80)
toys = models.ManyToManyField('Toy', related_name="owner")
class Toy(models.Model):
name = models.CharField(max_length=80)
You can query the toys for a specific parent by using field lookups.
您可以使用字段查找查询特定父级的玩具。
Toy.objects.filter(owner__parent__id=1)
Or:
要么:
Toy.objects.filter(owner__parent=parent)
The resulting SQL looks something like this:
生成的SQL看起来像这样:
SELECT "toy"."id", "toy"."name" FROM "toy"
INNER JOIN "child_toys"
ON ("toy"."id" = "child_toys"."toy_id")
INNER JOIN "child"
ON ("child_toys"."child_id" = "child"."id")
INNER JOIN "parent_children"
ON ("child"."id" = "parent_children"."child_id")
WHERE "parent_children"."parent_id" = 1
#1
7
Simply write something like:
只需写下以下内容:
Toy.objects.filter(toy_owners__parents=parent)
#2
2
If you don't store extra information in the intermediate tables Parent_Child
and Child_Toy
you can just leave them out - Django will create them automatically for you. So a simplified setup would look like this:
如果你不在中间表Parent_Child和Child_Toy中存储额外的信息,你可以将它们遗漏--Django将自动为你创建它们。所以简化的设置看起来像这样:
class Parent(models.Model):
name = models.CharField(max_length=80)
children = models.ManyToManyField('Child', related_name="parent")
class Child(models.Model):
name = models.CharField(max_length=80)
toys = models.ManyToManyField('Toy', related_name="owner")
class Toy(models.Model):
name = models.CharField(max_length=80)
You can query the toys for a specific parent by using field lookups.
您可以使用字段查找查询特定父级的玩具。
Toy.objects.filter(owner__parent__id=1)
Or:
要么:
Toy.objects.filter(owner__parent=parent)
The resulting SQL looks something like this:
生成的SQL看起来像这样:
SELECT "toy"."id", "toy"."name" FROM "toy"
INNER JOIN "child_toys"
ON ("toy"."id" = "child_toys"."toy_id")
INNER JOIN "child"
ON ("child_toys"."child_id" = "child"."id")
INNER JOIN "parent_children"
ON ("child"."id" = "parent_children"."child_id")
WHERE "parent_children"."parent_id" = 1