我想在自定义订单中选择表格中的项目, 使用SQL,如果未指定顺序,则使用升序主键,因此“IN”顺序将丢失。 我在SO中读到可以使用此SQL请求来保持“IN”顺序:
SELECT * FROM table WHERE id IN (118,17,113,23,72) ORDER BY FIELD(id,118,17,113,23,72)
现在,我该如何在django中编写此请求? 注意:我不想使用.in_bulk()queryset方法,因为我希望SQL能够完成这项工作。
答案 0 :(得分:3)
您可以使用Django 1.2 +中的raw()
管理器方法执行此操作。
ids = "118,17,113,23,72"
results = MyModel.objects.raw('SELECT * FROM myapp_mymodel WHERE `id` IN (%s) '
'ORDER BY FIELD (id, %s)' % (ids, ids))
一些注意事项:
这可能容易受到SQL注入攻击,因为您无法对ORDER BY元素使用参数处理。请务必清理ids
列表。
raw()
不会像普通查询集一样缓存查询 - 它会在每次迭代时重新评估查询。如果您需要多次使用这些值,请先在其上调用list()
。
ORDER BY FIELD
是特定于MySQL的扩展程序。
另请注意,您的最终请求没有意义:in_bulk()
确实使用SQL来完成工作。但是,它无论如何都不适合您的查询。
答案 1 :(得分:0)
我试过这个:
from django.db.models import Q
# first you get the IDs
ids = [1,2,3,4,5]
# after that you can get a list of Q objects
q_objects = [Q(id=id) for id in ids]
# then you need to combine all the Q objects
# I'll use a functional approach, an operation called fold_left but you can use a for instead
# i need the first element
first_q = q_objects.pop()
final_q = reduce(lambda total,q: total | q,q_objects,first_q)
# now you can get the result
MyModel.objects.filter(q)
#if you need an order simply append order_by
MyModel.objects.filter(q).order_by(something)
无论如何,请查看in_bulk
执行的查询,因为它确实使用了IN SQL子句。这是对django 1.3和MySQL的测试:
python manage.py shell
>>> from testapp.models import Car
>>> from django.db import connection
>>> cars = Car.objects.in_bulk([1,2])
>>> my_queries = connection.queries
>>> my_queries[0]['sql']
这是SQL结果:
SELECT [fields]
FROM [my_table] WHERE [my_model].`id` IN (1, 2)
当然你只能使用django_toolbar。