[Django][DRF] 如何从 .filter 获取未排序的查询集?
[Django][DRF] How to get UNORDERED queryset from `.filter`?
首先,我不是 ENG 的本地人,所以请耐心等待我的 ENG 技能或给我一些建议。
(仅供参考,Django ver 3.2.9 & DRF ver 3.12.4 with postgres ver 12.7)
我正在编写 API 通过使用 drf 序列化程序创建一个 post。我一直面临“添加到 post 的标签顺序”的问题。
- post和标签模型通过M2M领域连接
这意味着,假设我在 post 上添加了标签 a、b 和 c。我使用的逻辑如下。
# class Serializer
# def create(instance):
# instance : specific post instance
tags = ['t', 'a', 'g', 's']
Tag.objects.bulk_create([Tag(name = tag) for tag in tags])
instance.tags.add(*[tag for tag in Tag.objects.filter(name__in = tags)])
运行先这样。标签按此顺序添加
TagQuerySet[Tag<'t'>, Tag<'a'>, Tag<'g'>, Tag<'s'>]
我的 API 接受了另一个包含现有标签的创建请求,
tags = ['g', 'a', 's']
django按照排序的顺序添加,不是我想要的顺序,
# tags new created instance
TagQuerySet[Tag<'a'>, Tag<'g'>, Tag<'s'>]
我知道使用 for 循环在我的列表顺序后添加标签的方法
for tag in tags:
instance.tags.add(Tag.objects.get(name=tag))
但效率不高
所以我的问题是
- 如何按照我的列表顺序使用
.filter
获取查询集。
- 如果没有办法。将标签添加到 post
的有效方法是什么
您可以向标记 class 添加另一列,即优先级,每当您插入行时添加值的优先级。
然后您可以像这样按优先顺序排序:
tags = [('t', 4), ('a', 2), ('g', 1), ('s', 3)]
Tag.objects.bulk_create([Tag(name = tag[0], priority=tag[1]) for tag in tags])
Tag.objects.all().order_by('priority')
也是这个的优化版本:
for tag in tags:
instance.tags.add(Tag.objects.get(name=tag))
这是:
tags_db = Tag.objects.filter(name__in=[tag for tag in tags])
instance.tags.set(list(tags_db))
编辑:
使用 python 排序:
my_order_list = ['g', 'a', 's', 't']
sorted(Tag.objects.all(), key=lambda x: my_order_list.index(x.name))
使用 sql 个大小写表达式排序:
Tag.objects.raw("
SELECT * FROM Tag ORDER BY
CASE name
WHEN 'g' THEN 1
WHEN 'a' THEN 2
WHEN 's' THEN 3
ELSE 4
END
")
首先,我不是 ENG 的本地人,所以请耐心等待我的 ENG 技能或给我一些建议。
(仅供参考,Django ver 3.2.9 & DRF ver 3.12.4 with postgres ver 12.7)
我正在编写 API 通过使用 drf 序列化程序创建一个 post。我一直面临“添加到 post 的标签顺序”的问题。
- post和标签模型通过M2M领域连接
这意味着,假设我在 post 上添加了标签 a、b 和 c。我使用的逻辑如下。
# class Serializer
# def create(instance):
# instance : specific post instance
tags = ['t', 'a', 'g', 's']
Tag.objects.bulk_create([Tag(name = tag) for tag in tags])
instance.tags.add(*[tag for tag in Tag.objects.filter(name__in = tags)])
运行先这样。标签按此顺序添加
TagQuerySet[Tag<'t'>, Tag<'a'>, Tag<'g'>, Tag<'s'>]
我的 API 接受了另一个包含现有标签的创建请求,
tags = ['g', 'a', 's']
django按照排序的顺序添加,不是我想要的顺序,
# tags new created instance
TagQuerySet[Tag<'a'>, Tag<'g'>, Tag<'s'>]
我知道使用 for 循环在我的列表顺序后添加标签的方法
for tag in tags:
instance.tags.add(Tag.objects.get(name=tag))
但效率不高
所以我的问题是
- 如何按照我的列表顺序使用
.filter
获取查询集。 - 如果没有办法。将标签添加到 post 的有效方法是什么
您可以向标记 class 添加另一列,即优先级,每当您插入行时添加值的优先级。
然后您可以像这样按优先顺序排序:
tags = [('t', 4), ('a', 2), ('g', 1), ('s', 3)]
Tag.objects.bulk_create([Tag(name = tag[0], priority=tag[1]) for tag in tags])
Tag.objects.all().order_by('priority')
也是这个的优化版本:
for tag in tags:
instance.tags.add(Tag.objects.get(name=tag))
这是:
tags_db = Tag.objects.filter(name__in=[tag for tag in tags])
instance.tags.set(list(tags_db))
编辑:
使用 python 排序:
my_order_list = ['g', 'a', 's', 't']
sorted(Tag.objects.all(), key=lambda x: my_order_list.index(x.name))
使用 sql 个大小写表达式排序:
Tag.objects.raw("
SELECT * FROM Tag ORDER BY
CASE name
WHEN 'g' THEN 1
WHEN 'a' THEN 2
WHEN 's' THEN 3
ELSE 4
END
")