Django ORM 替换额外的 where

Posted

技术标签:

【中文标题】Django ORM 替换额外的 where【英文标题】:Django ORM replacement for extra where 【发布时间】:2020-11-06 05:05:45 【问题描述】:

这是我目前计划使用 .extra(where=...) 调用解决的一个场景:

class CustomData(models.Model):
   data = models.CharField()
   target_type = models.ForeignKey(ContentType)
   target_object_id = models.PositiveInteger()
   target_object = GenericForeignKey('target_type', 'target_object_id')

# list of tuples with object ID and mixed content type ID [(1, 15), (2, 15), (3, 11), (4, 12), ...]
related_objects = get_list_of_objects(...)
releated_custom_data = CustomData.objects.extra(
      where=['(target_object_id, target_type_id) = ANY (VALUES %s)'], 
      params=str(related_objects)[1:-1]
)

基于 django docs 的额外功能将在未来被弃用。使用 ORM 进行值对过滤是否有明智的选择?

【问题讨论】:

【参考方案1】:

您可以创建一个Q 对象来过滤两者的组合,例如:

from django.db.models import Q

data = [(1, 15), (2, 15), (3, 11), (4, 12)]
q_filter = Q(
    *[Q(target_object_id=d1, target_type_id=d2) for d1, d2 in data],
    _connector=Q.OR
)

CustomData.objects.filter(q_filter)

【讨论】:

谢谢。这会起作用,但这显然会失去在 PostgreSQL 中使用 ANY 的好处,它提供比一系列 OR 子句更好的查询性能。有什么想法吗?

以上是关于Django ORM 替换额外的 where的主要内容,如果未能解决你的问题,请参考以下文章

如何将额外的参数传递给 django admin 自定义表单?

丰富 Eloquent ORM 的 where 查询条件的解析场景

有没有办法通过 Django ORM 查询修改日期时间对象?

django知识点总结

基于 WHERE 的带有额外手动输出的 MySQL 查询

Django 使用 ORM 和条件 Where 子句连接表