我正在使用Django的内置用户模型,并拥有一个带有ForeignKey to User的自定义Foo对象.我想要选择所有User对象和所有符合某些约束的Foo对象,如下所示:
SELECT * from auth_user LEFT OUTER JOIN "foo" ON
(auth_user.id = foo.id AND <other criteria here>)
Run Code Online (Sandbox Code Playgroud)
我应该如何在Django中实现这一目标?到目前为止,我已经尝试过:
User.objects.filter(foo__<criteria>)
Run Code Online (Sandbox Code Playgroud)
但是这会生成与此类似的SQL:
SELECT * from auth_user LEFT OUTER JOIN "foo" ON
(auth_user.id = foo.id) WHERE <other criteria here>
Run Code Online (Sandbox Code Playgroud)
并且仅返回具有符合条件的Foo对象的User对象.或者,我可以选择所有用户对象并为每个对象运行查询,但这样效率会大大降低.
Ric*_*ech 15
要得到一个LEFT OUTER JOIN
你可以去:
User.objects.select_related('foo').filter(Q(foo__isnull=True) | Q(<other criteria here>))
Run Code Online (Sandbox Code Playgroud)
Django 使用foo__isnull=True
来指示它生成一个LEFT OUTER JOIN
. 给予foo__isnull=False
以生成一个,INNER JOIN
就像没有过滤器参数一样。
Django 2.0 引入了FilteredRelation
对象,它可以生成几乎完全相同的LEFT OUTER JOIN
查询,代码类似于:
User.objects.annotate(
filtered_foo=FilteredRelation('foo', condition=Q(foo_<criteria>))
).values(...) # e.g. 'user__id', 'filtered_foo__id'
Run Code Online (Sandbox Code Playgroud)
但是,您似乎需要通过在附加注释中指定或使用附加注释来明确询问filtered_foo
要使用的字段。values
或者,您还可以对filtered_foo
按用户分组的字段进行聚合。
如果您希望 Django 获取所有User
对象以及Foo
与用户对象相关的所有对象,那么您可以使用select_related()
:
User.objects.all().select_related('foo')
Run Code Online (Sandbox Code Playgroud)
但在这里您不需要与用户对象相关的所有对象,您只需要满足您的条件的它们的子集。Foo
我不知道如何告诉 Django 在单个查询集中执行此操作。但你可以做的是分别进行两个选择并在 Python 中进行连接:
# Map from user id to corresponding Foo satisfying <criteria>, if any.
foos = {foo.user_id: foo for foo in
Foo.objects.filter(user__isnull = False, <criteria>)}
for user in User.objects.all():
foo = foos.get(user.id)
# ...
Run Code Online (Sandbox Code Playgroud)
(这不会比您做更多的数据库工作或传输更多的数据LEFT OUTER JOIN
,所以我认为这是一个合理的方法。)
归档时间: |
|
查看次数: |
10326 次 |
最近记录: |