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测试中的执行顺序是啥

如何根据 Solr 中的顺序过滤结果?

mysql的关键词执行顺序

使用 Django ORM 使用 UNION 指定 SELECT 中的列顺序

如何通过 GraphQL 中的过滤器和顺序动态创建/获取数据?

django中的中间件机制和执行顺序