我正在尝试进行连续的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
而不是pk
或created
排序。但是如果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]
但是我认为这不是一个好主意。这似乎不是最好的主意。
问题:如何更好地解决它?如何过滤?
答案 0 :(得分:1)
您可以使用以下事实:QuerySet
是一个集合,因此支持these set operators,其中一个是difference()
。因此,如果您有一个要从另一个查询集(qs1
中排除的查询集(qs2
),则可以执行以下操作:
qs2 = qs2.difference(qs1)
请注意,您的qs2
查询不应在应用差异之前进行切片,因为切片应始终是最后的操作。否则,您可能会遇到SQL错误。