简介
相对较新的django,好奇如何使用ORM为我的特定用例进行4向连接。
Django模型
class Foo( models.Model ):
attr1 = ...
class Bar( models.Model ):
foo = models.ForeignKey ( Foo )
attr2 = ...
class BarOneToOne( models.Model ):
bar = models.ForeignKey ( Bar )
attr3 = ...
class BarManyToOne( models.Model ):
bar = models.ForeignKey ( Bar )
attr4 = ...
问题
想要包含关联的BarManyToOne
,BarOneToOne
和Bar
数据的Foo
列表。想要根据Foo
ID对其进行过滤。
示例
数据:
Foo Bar
-------------- -----------------------
| id | attr1 | | id | attr2 | foo_id |
-------------- -----------------------
1 apple 101 larry 1
2 orange 102 bob 2
3 pear 103 sue 3
4 grape 104 laura 1
105 nancy 4
BarOneToOne BarManyToOne
------------------ --------------------
| bar_id | attr3 | | bar_id | attr4 |
------------------ --------------------
101 dog 101 cinnamon
103 mouse 104 thyme
104 cat 103 garlic
104 sea salt
101 chili powder
103 paprika
期望的结果:
--------------------------------------
| apple | larry | dog | cinnamon |
--------------------------------------
| apple | laura | cat | thyme |
--------------------------------------
| apple | laura | cat | sea salt |
--------------------------------------
| apple | larry | dog | chili powder |
--------------------------------------
SQL等效
SELECT f.attr1, b.attr2, bmto.attr3, bmtoa.attr4
FROM foo f, bar b, bar_one_to_one boto, bar_many_to_one bmto
WHERE bmto.bar_id = boto.bar_id AND b.id = bmto.bar_id
AND b.foo_id = f.id AND f.id = ?;
其它
到目前为止,我在文档中看到select_related
,感觉非常有用。也是__方法。感觉就像碎片在这里,但尚未能将它们整合在一起。
在性能/大小方面,Foo,Bar和BarOneToOne表都很小(每行500行以下,甚至可能每行不超过100行)。 BarManyToOne表将更大。
提前致谢。
答案 0 :(得分:0)
您需要根据参考框架为模型设置related_names。有很多方法可以做到这一点,但为了这个目的,我将使用BarManyToOne
表作为主表。
class Foo( models.Model ):
attr1 = ...
class Bar( models.Model ):
foo = models.ForeignKey ( Foo, related_name='foo_bars')
attr2 = ...
class BarOneToOne( models.Model ):
bar = models.ForeignKey ( Bar, related_name='bar_baronetoones' )
attr3 = ...
class BarManyToOne( models.Model ):
bar = models.ForeignKey ( Bar, related_name='bar_barmanytoones' )
attr4 = ...
使用上面显示的模型设置,这将是您需要调用以获取SQL查询等效的代码。
BarManyToOne.objects.all().select_related(
'bar', # Joins the three other tables
'bar__foo', # with BarManyToOne serving as
'bar__bar_baronetoones' # the main table
).filter( # Your (non join condition) WHERE clauses
bar__foo_id=<your value here> # f.id = ?
).values( # The columns you want
'bar__foo__attr1', # f.attr1
'bar__attr2', # b.attr2
'bar__bar_baronetoones__attr3', # boto.attr3
'attr4' # bmto.attr4
)
您需要阅读related_name,the making queries section和F() expressions。