Better Alternate 而不是在 Django ORM 中使用链式联合查询
Better Alternate instead of using chained union queries in Django ORM
我需要在 Django ORM 中实现类似的功能:
(SELECT * FROM `stats` WHERE MODE = 1 ORDER BY DATE DESC LIMIT 2)
UNION
(SELECT * FROM `stats` WHERE MODE = 2 ORDER BY DATE DESC LIMIT 2)
UNION
(SELECT * FROM `stats` WHERE MODE = 3 ORDER BY DATE DESC LIMIT 2)
UNION
(SELECT * FROM `stats` WHERE MODE = 6 ORDER BY DATE DESC LIMIT 2)
UNION
(SELECT * FROM `stats` WHERE MODE = 5 AND is_completed != 3 ORDER BY DATE DESC)
# mode 5 can return more than 100 records so NO LIMIT here
为此我写了这个:
query_run_now_job_ids = Stats.objects.filter(mode=5).exclude(is_completed=3).order_by('-date')
list_of_active_job_ids = Stats.objects.filter(mode=1).order_by('-date')[:2].union(
Stats.objects.filter(mode=2).order_by('-date')[:2],
Stats.objects.filter(mode=3).order_by('-date')[:2],
Stats.objects.filter(mode=6).order_by('-date')[:2],
query_run_now_job_ids)
但不知何故 list_of_active_job_ids 返回的是无序的,即 list_of_active_job_ids.ordered
returns False 由于当这个查询被传递给 Paginator class 它给出:
UnorderedObjectListWarning:
Pagination may yield inconsistent results with an unordered object_list
我已经在 models.py
的 class Meta 中设置了顺序
class Meta:
ordering = ['-date']
没有分页器查询工作正常,页面加载但使用分页器,视图从不加载它一直在加载。
有没有更好的替代方案可以在不使用联合链的情况下实现这一目标。
所以我为上面的 mysql 查询尝试了另一个替代方法,但我陷入了另一个问题,无法为 mode = 5[ 编写条件=45=] 在这个查询中:
SELECT
MODE ,
SUBSTRING_INDEX(GROUP_CONCAT( `job_id` SEPARATOR ',' ),',',2) AS job_id_list,
SUBSTRING_INDEX(GROUP_CONCAT( `total_calculations` SEPARATOR ',' ),',',2) AS total_calculations
FROM `stats`
ORDER BY DATE DESC
即使我能够编写此查询,它也会将我带到另一个具有挑战性的情况,即将此查询转换为 Django ORM。
为什么我的查询没有被排序,即使我已经在 Class Meta 中设置了它。
此外,如果不是这个查询,是否有更好的替代方法来实现这个?
帮助将不胜感激! .
我正在使用 Python 2.7 和 Django 1.11。
虽然子查询可能是有序的,但生成的联合数据却不是。您需要明确定义顺序。
from django.db import models
def make_query(mode, index):
return (
Stats.objects.filter(mode=mode).
annotate(_sort=models.Value(index, models.IntegerField())).
order_by('-date')
)
list_of_active_job_ids = make_query(1, 1)[:2].union(
make_query(2, 2)[:2],
make_query(3, 3)[:2],
make_query(6, 4)[:2],
make_query(5, 5).exclude(is_completed=3)
).order_by('_sort', '-date')
我所做的只是添加一个新的文字值字段 _sort
,每个子查询都有不同的值,然后在最后的代码中按它排序 query.The 代码的其余部分只是为了减少复制。如果不是那个 mode=6
子查询,它会更干净。
我需要在 Django ORM 中实现类似的功能:
(SELECT * FROM `stats` WHERE MODE = 1 ORDER BY DATE DESC LIMIT 2)
UNION
(SELECT * FROM `stats` WHERE MODE = 2 ORDER BY DATE DESC LIMIT 2)
UNION
(SELECT * FROM `stats` WHERE MODE = 3 ORDER BY DATE DESC LIMIT 2)
UNION
(SELECT * FROM `stats` WHERE MODE = 6 ORDER BY DATE DESC LIMIT 2)
UNION
(SELECT * FROM `stats` WHERE MODE = 5 AND is_completed != 3 ORDER BY DATE DESC)
# mode 5 can return more than 100 records so NO LIMIT here
为此我写了这个:
query_run_now_job_ids = Stats.objects.filter(mode=5).exclude(is_completed=3).order_by('-date')
list_of_active_job_ids = Stats.objects.filter(mode=1).order_by('-date')[:2].union(
Stats.objects.filter(mode=2).order_by('-date')[:2],
Stats.objects.filter(mode=3).order_by('-date')[:2],
Stats.objects.filter(mode=6).order_by('-date')[:2],
query_run_now_job_ids)
但不知何故 list_of_active_job_ids 返回的是无序的,即 list_of_active_job_ids.ordered
returns False 由于当这个查询被传递给 Paginator class 它给出:
UnorderedObjectListWarning:
Pagination may yield inconsistent results with an unordered object_list
我已经在 models.py
的 class Meta 中设置了顺序class Meta:
ordering = ['-date']
没有分页器查询工作正常,页面加载但使用分页器,视图从不加载它一直在加载。
有没有更好的替代方案可以在不使用联合链的情况下实现这一目标。
所以我为上面的 mysql 查询尝试了另一个替代方法,但我陷入了另一个问题,无法为 mode = 5[ 编写条件=45=] 在这个查询中:
SELECT
MODE ,
SUBSTRING_INDEX(GROUP_CONCAT( `job_id` SEPARATOR ',' ),',',2) AS job_id_list,
SUBSTRING_INDEX(GROUP_CONCAT( `total_calculations` SEPARATOR ',' ),',',2) AS total_calculations
FROM `stats`
ORDER BY DATE DESC
即使我能够编写此查询,它也会将我带到另一个具有挑战性的情况,即将此查询转换为 Django ORM。
为什么我的查询没有被排序,即使我已经在 Class Meta 中设置了它。
此外,如果不是这个查询,是否有更好的替代方法来实现这个?
帮助将不胜感激! .
我正在使用 Python 2.7 和 Django 1.11。
虽然子查询可能是有序的,但生成的联合数据却不是。您需要明确定义顺序。
from django.db import models
def make_query(mode, index):
return (
Stats.objects.filter(mode=mode).
annotate(_sort=models.Value(index, models.IntegerField())).
order_by('-date')
)
list_of_active_job_ids = make_query(1, 1)[:2].union(
make_query(2, 2)[:2],
make_query(3, 3)[:2],
make_query(6, 4)[:2],
make_query(5, 5).exclude(is_completed=3)
).order_by('_sort', '-date')
我所做的只是添加一个新的文字值字段 _sort
,每个子查询都有不同的值,然后在最后的代码中按它排序 query.The 代码的其余部分只是为了减少复制。如果不是那个 mode=6
子查询,它会更干净。