【发布时间】: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 排序,而不是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]
但我认为这不是一个好主意。这似乎不是最好的主意。
问题:如何更好地解决?如何过滤?
【问题讨论】:
-
查询集是集合,因此支持您可以使用的these set operators。例如,如果您想从
qs2中排除所有qs1元素,您可以使用qs2 = qs2.difference(qs1)。请注意,您可能不想分割您的 QuerySet ([:5])qs2,直到 从qs1中删除元素。 -
我不明白的问题是为什么你需要 4 个不同的查询集。通常您会使用Pagination 将结果分成 5 个一组:首先按文本长度排序,然后分页。每个页面都会有接下来的 5 个结果。
-
@dirkgroten 抱歉,在我的情况下分页不好。
-
@dirkgroten 您的第一条评论会很好,我会将您的建议保留在我的笔记中。谢谢