django不断变化的过滤器

时间:2018-11-28 13:41:00

标签: python django filter

我正在尝试进行连续的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]

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

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

1 个答案:

答案 0 :(得分:1)

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

qs2 = qs2.difference(qs1)

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