django中的过滤顺序
Posted
技术标签:
【中文标题】django中的过滤顺序【英文标题】:Filtering order in django 【发布时间】:2017-10-29 08:43:36 【问题描述】:我有兴趣按特定顺序按 django orm 过滤表。基本上,这是通过两个字段进行的简单搜索 - 名称和描述。我想首先按“名称”字段并发对结果进行排序,然后按“描述”字段并发排序。以下是原始 sql 的示例:
WITH checkpoints AS (SELECT *
FROM checkpoints_view
WHERE ...)
SELECT *
FROM checkpoints
WHERE name ILIKE '%KEYWORD%'
UNION ALL SELECT *
FROM checkpoints
WHERE description ILIKE '%KEYWORD%' AND name NOT ILIKE '%KEYWORD%';
如何在 django orm 中生成这样的 sql?
谢谢大家
P.S.:对不起,如果我的英语不正确,我来自非英语国家
class Checkpoint(models.Model, ReadOnlyModel):
id = models.IntegerField(primary_key=True)
name = models.CharField(max_length=255, verbose_name='Наименование')
code_number = models.CharField(max_length=255, verbose_name="Код остановки")
description = models.CharField(max_length=255, verbose_name="Описание")
coordinate = models.PointField(verbose_name="Координата")
routes = ArrayField(models.IntegerField())
dates = ArrayField(models.DateField())
class Meta:
db_table = 'checkpoints_view'
managed = False
几乎所有人都对,但我希望结果是按行开始排序的,它通过了名称字段的过滤器,然后,在这一切之后 - 行,它通过了描述字段的过滤器
【问题讨论】:
请分享您的模型 【参考方案1】:我认为您的代码可以在没有 CTE 的情况下编写:
Checkpoint.objects.filter(
Q(name__icontains='keyword') |
(~Q(name__icontains='keyword') & Q(description__icontains='keyword')))
【讨论】:
你有什么问题??你为什么只对我的回答投反对票??我对你做了什么 ??其他人给出了相同的答案,但您特别反对我的答案? @Exprator 你来这里是为了获得轻松的 SO 声誉。您提到的另一个解决方案将返回正确的结果,尽管它不是最佳解决方案。您的解决方案不能解决问题 - 如果您思考或尝试,您会发现它会给出与问题中发布的查询不同的结果。没有什么私人的,我看到一个不正确的答案并投了反对票。 说“不是最佳解决方案”让我觉得因为我总是使用我的解决方案(我认为它更具可读性,但不知道它可能效率较低)所以尝试了两种解决方案(我的和你的)在一个简单的 django 模型上,使用非常简单的查询(pk>10) or (pk < 10 and pk !=3)
并使用 print(q.query)
检查 django sql 查询,它们都生成了相同的 sql 查询。
我不确定复杂查询,可能复杂查询不同
@aliva 最好安装django-extensions
包并使用./manage.py debugsqlshell
,它更方便并且会将所有查询打印到控制台。当我说您的解决方案不是最佳时,我错了 - 我检查了一下,似乎 Django 在您的情况下也生成了最佳 SQL 查询。【参考方案2】:
AFAIK,Django ORM 在它生成的查询中不使用 CTE。那是因为它们在不同的 RDBMS 中具有不同的行为,并且在 mysql 和 sqlite 中根本不支持。
因此,如果您想在查询中使用 CTE,您唯一的选择是 raw query。类似的东西
queryset = MyModel.objects.raw('WITH checkpoints AS (SEL ....')
【讨论】:
这是问题所在,它现在已经在原始 sql 上工作,但我想用 django orm 方式实现这个谢谢你的回答 顺便说一句,我并不是说严格使用“WITH”关键字,它可以是两个选择并联合。 你问了一个问题,我们回答了。您的想法我们无法回答。【参考方案3】:results = Checkpoint.objects.filter(
name__icontains='str_1',
) | Checkpoint.objects.filter(
description__icontains='str_2',
).exclude(
name__icontains='str_3',
)
【讨论】:
以上是关于django中的过滤顺序的主要内容,如果未能解决你的问题,请参考以下文章
使用 Django ORM 使用 UNION 指定 SELECT 中的列顺序