【问题标题】:[Django][DRF] How to get UNORDERED queryset from `.filter`?[Django][DRF] 如何从 .filter 获取 UNORDERED 查询集?
【发布时间】:2022-01-26 04:21:45
【问题描述】:

首先,我不是 ENG 的本地人,所以请耐心等待我的 ENG 技能或给我一些建议。

(仅供参考,Django 版本 3.2.9 和 DRF 版本 3.12.4 和 postgres 版本 12.7)

我正在编写使用 drf 序列化程序创建帖子的 API。而且我一直面临“添加到帖子的标签顺序”的问题。

  • post 和 tag 模型通过 M2M 字段连接

这意味着,假设我在帖子上添加标签 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 add 按排序的顺序,而不是我想要的顺序,

# 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 获取查询集。
  • 如果没有办法。给帖子添加标签的有效方法是什么

【问题讨论】:

    标签: django filter django-rest-framework orm m2m


    【解决方案1】:

    您可以向 Tag 类添加另一列,即优先级,并且每当您插入行时添加值的优先级。

    然后你可以像这样按优先级排序:

    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 case 表达式排序:

    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
    ")
    

    【讨论】:

    • 请您解答。您能否让我知道在不增加优先级的情况下按照我的列表排序获取查询集的任何其他方式?我想,添加优先级会使我的队友因迁移而感到不便。
    • 你使用的是哪个数据库?
    • 我正在使用 postgresql!
    • @SeojunYoun 检查我的答案已编辑
    • 我想我需要使用优先级。谢谢哥们!
    猜你喜欢
    • 1970-01-01
    • 2019-04-03
    • 2020-01-27
    • 2021-05-07
    • 2021-12-10
    • 2015-10-17
    • 2020-11-06
    • 2015-03-20
    • 1970-01-01
    相关资源
    最近更新 更多