Cau*_*ons 14 python django django-queryset
我想在Django中追加或链接几个Queryset,保留每个Queryset的顺序(不是结果).我正在使用第三方库对结果进行分页,它只接受列表或查询集.我试过这些选项:
Queryset join:不保留单个查询集中的排序,因此我不能使用它.
result = queryset_1 | queryset_2
Run Code Online (Sandbox Code Playgroud)
使用itertools:调用list()链对象实际上会评估查询集,这可能会导致很多开销.不是吗?
result = list(itertools.chain(queryset_1, queryset_2))
Run Code Online (Sandbox Code Playgroud)
你觉得我该怎么办?
小智 13
此解决方案可防止重复:
q1 = Q(...)
q2 = Q(...)
q3 = Q(...)
qs = (
Model.objects
.filter(q1 | q2 | q3)
.annotate(
search_type_ordering=Case(
When(q1, then=Value(2)),
When(q2, then=Value(1)),
When(q3, then=Value(0)),
default=Value(-1),
output_field=IntegerField(),
)
)
.order_by('-search_type_ordering', ...)
)
Run Code Online (Sandbox Code Playgroud)
小智 6
如果查询集具有不同的模型,则必须将它们评估为列表,然后您可以添加:
result = list(queryset_1) + list(queryset_2)
Run Code Online (Sandbox Code Playgroud)
如果它们是相同的模型,则应使用Q对象和'order_by("queryset_1 field","queryset_2 field")'组合查询.
正确的答案在很大程度上取决于您希望将这些结合起来以及如何使用结果的原因.
因此,受到彼得回答的启发,这就是我在我的项目(Django 2.2)中所做的:
from django.db import models
from .models import MyModel
# Add an extra field to each query with a constant value
queryset_0 = MyModel.objects.annotate(
qs_order=models.Value(0, models.IntegerField())
)
# Each constant should basically act as the position where we want the
# queryset to stay
queryset_1 = MyModel.objects.annotate(
qs_order=models.Value(1, models.IntegerField())
)
[...]
queryset_n = MyModel.objects.annotate(
qs_order=models.Value(n, models.IntegerField())
)
# Finally, I ordered the union result by that extra field.
union = queryset_0.union(
queryset_1,
queryset_2,
[...],
queryset_n).order_by('qs_order')
Run Code Online (Sandbox Code Playgroud)
有了这个,我可以根据需要对结果联合进行排序,而无需更改任何私有属性,而只对查询集进行一次评估。
| 归档时间: |
|
| 查看次数: |
4490 次 |
| 最近记录: |