回答

收藏

Django左外连接带过滤器

技术问答 技术问答 197 人阅读 | 0 人回复 | 2023-09-14

我正在使用Django的内置用户模型,并且具有一个自定义Foo对象,并带有一个用户外键。我正在寻找选择所有User对象和所有符合某些约束的Foo对象,例如:
9 o" K* o9 `5 ?8 y- qSELECT * from auth_user LEFT OUTER JOIN "foo" ON6 L$ g2 K( C2 {+ `
(auth_user.id = foo.id AND )& J/ P" b* J8 a+ f
我应该如何在Django中完成这项工作?到目前为止,我已经尝试过:
* [$ @* C9 n) q& ]/ Q% G6 P( c& f$ tUser.objects.filter(foo__)
, ]  ~- d/ G* O/ e! l* J; A但这会生成类似于以下内容的SQL:/ L; `4 L. _; e) ~" w
SELECT * from auth_user LEFT OUTER JOIN "foo" ON: R0 R. y, I  o
(auth_user.id = foo.id) WHERE ) t7 r) E: f# [3 C  _
并且仅返回具有符合条件的Foo对象的User对象。或者,我可以选择所有User对象并为每个对象运行一个查询,但是效率会大大降低。
; x% U# T6 a  M               
' z$ n3 {" a. @% q; e; t解决方案:( S! t% \5 l6 M. [, D* F. \
               
4 o) ?9 k. I( R7 I
% [" Y; m- k* P/ p; Z9 B; F6 Y1 I' S
/ j( l4 s- t: Q! J5 N7 ]- V                如果您希望Django提取所有User对象以及Foo与用户对象相关的所有对象,则可以使用select_related():
/ T2 h" v( R( s) vUser.objects.all().select_related('foo')
+ D# k" J* a+ g' K! p. I但在这里,你不希望 所有3 {6 f4 h" s* @0 c
的Foo那些与用户对象的对象,你只是希望他们的满足您的标准的子集。我不知道一种告诉Django在单个查询集中执行此操作的方法。但是您 可以
5 q- G5 f6 `& [: x; l! Y/ N# i8 a做的是分别进行两个选择并在Python中进行联接:, t' |4 F3 j! w7 B2 O9 ?4 }
# Map from user id to corresponding Foo satisfying , if any.4 B% [9 ]7 l5 Z6 o
foos = {foo.user_id: foo for foo in 0 @# \+ i5 U) a9 I
        Foo.objects.filter(user__isnull = False, )}
! e. u" M* P! \' q% G: mfor user in User.objects.all():
5 c, c# ?/ y6 j6 N# y* B    foo = foos.get(user.id)# X' O+ x2 C( ~9 l; d
    # ...
' A9 W9 M$ y3 T. }& Y8 r6 W8 m(这不会比您做更多的数据库工作或传输更多的数据LEFT OUTER JOIN,因此我认为这是一种合理的方法。)
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则