gpt4 book ai didi

django - 以自定义顺序获取多个对象的优雅方式

转载 作者:行者123 更新时间:2023-12-02 02:24:07 26 4
gpt4 key购买 nike

从 django 中的数据库中以某种自定义顺序获取多个对象的优雅方法是什么?

例如,假设您有一些产品,每个产品都有其名称,并且您想要获取其中三个产品以按某种固定的自定义顺序在您的网站页面上连续显示。假设您要显示的产品名称按顺序为:["Milk", "Chocolate", "Juice"]

一个人可以做到

unordered_products = Product.objects.filter(name__in=["Milk", "Chocolate", "Juice"])
products = [
unordered_products.filter(name="Milk")[0],
unordered_products.filter(name="Chocolate")[0],
unordered_products.filter(name="Juice")[0],
]

提取后排序部分可以改进为使用 name 索引字典:

ordered_product_names = ["Milk", "Chocolate", "Juice"]
products_by_name = dict((x.name, x) for x in unordered_products)
products = [products_by_name[name] for name in ordered_product_names]

但是有没有更优雅的方式呢?例如,以某种方式将所需的顺序传达给数据库层,或者返回按名称分组的产品(聚合似乎与我想要的类似,但我想要实际的对象,而不是有关它们的统计信息)。

最佳答案

您可以通过自定义订单订购您的产品,只需使用 ORM 的一个查询(仅执行一个 SQL 查询):

ordered_products = Product.objects.filter(
name__in=['Milk', 'Chocolate', 'Juice']
).annotate(
order=Case(
When(name='Milk', then=Value(0)),
When(name='Chocolate', then=Value(1)),
When(name='Juice', then=Value(2)),
output_field=IntegerField(),
)
).order_by('order')

更新

注意

谈到“优雅的方式”(和最佳实践),我认为绝对要避免额外方法(由@Satendra提出)。

Django 官方文档报告了此内容 extra :

Warning

You should be very careful whenever you use extra(). Every time you use it, you should escape any parameters that the user can control by using params in order to protect against SQL injection attacks . Please read more about SQL injection protection.

优化版本

如果您想仅使用一个查询来处理更多项目,您可以更改我的第一个查询并使用 Django ORM 灵 active ,如 @Shubhanshu 在他的回答中所建议的:

products = ['Milk', 'Chocolate', 'Juice']
ordered_products = Product.objects.filter(
name__in=products
).order_by(Case(
*[When(name=n, then=i) for i, n in enumerate(products)],
output_field=IntegerField(),
))

此命令的输出将类似于以下内容:

<QuerySet [<Product: Milk >, <Product: Chocolate>, <Product: Juice>]>

ORM生成的SQL将是这样的:

SELECT "id", "name"
FROM "products"
WHERE "name" IN ('Milk', 'Chocolate', 'Juice')
ORDER BY CASE
WHEN "name" = 'Milk' THEN 0
WHEN "name" = 'Chocolate' THEN 1
WHEN "name" = 'Juice' THEN 2
ELSE NULL
END ASC

关于django - 以自定义顺序获取多个对象的优雅方式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47389297/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com