【问题标题】:django chaning filter continuouslydjango 不断更换过滤器
【发布时间】:2018-11-28 13:40:59
【问题描述】:

我正在尝试进行连续的 django 过滤。

假设我有一些模型:

class TextModel(models.Model):
    text = models.TextField(max_length=1000, null=True, blank=True, default=None)
    created = models.DateTimeField(auto_now_add=True)

现在,我将像这样制作 TextModel 的对象:

{'text': '1'}, {'text': '2'} ... {'text': '99'}, {'text': '100'}

从这里开始我想做的事情。

我将通过 4 个查询集找到文本字段包含“1”的对象。

如你所知,最终结果是这样的:

{'text': '1'}, {'text':'10'}, {'text':'11'} ... {'text':'91'}, {'text':'100'}

也许它的长度是 20?可能有 20 个结果。

我想让这个结果除以 4 个分别有 5 个结果的查询集。我想让结果按他们的text length 排序,而不是pkcreated。但是如果text length是一样的,那么按'pk'或者'created'排序就好了。最紧急的订购标准是text length

我试过了:

from django.db.models import TextField
from django.db.models.functions import Length

TextField.register_lookup(Length)

qs1 = TextModel.objects.filter(Q(text__icontains='1')).order_by(
                    Length('text').asc(), 'pk')[:5]
qs2 = TextModel.objects.filter(Q(text__icontains='1') & Q(text__lte=len(qs1.last().text)).order_by(
                    Length('text').asc(), 'pk')[:5]
qs3 = TextModel.objects.filter(Q(text__icontains='1') & Q(text__lte=len(qs2.last().text)).order_by(
                    Length('text').asc(), 'pk')[:5]
qs4 = TextModel.objects.filter(Q(text__icontains='1') & Q(text__lte=len(qs3.last().text)).order_by(
                    Length('text').asc(), 'pk')[:5]

这失败了。因为qs2 也有同样在qs1 中的结果。

为了防止这种情况,我是这样想的:

qs1 = TextModel.objects.filter(Q(text__icontains='1')).order_by(
                    Length('text').asc(), 'pk')[:5]

qs2 = TextModel.objects.filter(Q(text__icontains='1') & Q(text__lte=len(qs1.last().text)).order_by(
                    Length('text').asc(), 'pk')[:5]

for item in qs1:
    qs2 = qs2.exclude(pk=item.pk)
qs2 = qs2.order_by(Length('text').asc(), 'pk')[:5]

但我认为这不是一个好主意。这似乎不是最好的主意。

问题:如何更好地解决?如何过滤?

【问题讨论】:

  • 查询集是集合,因此支持您可以使用的these set operators。例如,如果您想从qs2 中排除所有qs1 元素,您可以使用qs2 = qs2.difference(qs1)。请注意,您可能不想分割您的 QuerySet ([:5]) qs2,直到 qs1 中删除元素。
  • 我不明白的问题是为什么你需要 4 个不同的查询集。通常您会使用Pagination 将结果分成 5 个一组:首先按文本长度排序,然后分页。每个页面都会有接下来的 5 个结果。
  • @dirkgroten 抱歉,在我的情况下分页不好。
  • @dirkgroten 您的第一条评论会很好,我会将您的建议保留在我的笔记中。谢谢

标签: python django filter


【解决方案1】:

您可以使用QuerySet 是一个集合的事实,因此支持these set operators,其中一个是difference()。因此,如果您有一个查询集 (qs1) 想要从另一个查询集 (qs2) 中排除,您可以这样做:

qs2 = qs2.difference(qs1)

请注意,您的qs2 查询不应该在应用差异之前进行切片,因为切片应该始终是最后一个操作。否则你可能会遇到 SQL 错误。

【讨论】:

    猜你喜欢
    • 2021-04-29
    • 2021-07-03
    • 2018-07-11
    • 1970-01-01
    • 2014-01-30
    • 2023-04-06
    • 1970-01-01
    • 1970-01-01
    • 2016-10-08
    相关资源
    最近更新 更多