按列表中的值排序查询集

时间:2021-09-13 01:38:33

Is it possible to sort a django queryset by the list of elements provided in the query? For example, if I do

是否可以根据查询中提供的元素列表对django查询集进行排序?例如,如果我这么做

m.objects.filter(id__in=[3,1,8])

I wan't the order of the queryset to be the element of id 3, the element of id 1 and the element of id 8.

我不希望queryset的顺序是id 3的元素、id 1的元素和id 8的元素。

Thanks

谢谢

6 个解决方案

#1


5  

No. There is no way to do what you want short of some contrived mechanism like:

不。没有办法去做你想做的,缺少一些人为的机制:

qs = m.objects.filter(id__in=[3,1,8])
qs_sorted = list()
for id in [3,1,8]:
    qs_sorted.append(qs.get(id=id))

You'd need to throw some exception handling in there as well, just in case one of the specified ids wasn't actually returned.

您还需要在其中抛出一些异常处理,以防指定的id实际上没有返回。

The negatives are that this will effectively negate the lazy loading of queryset. In fact, it's very likely to generate multiple DB queries (haven't tested that though). Also, you end up with a normal python list instead of a queryset, so no more filtering is possible.

缺点是这将有效地消除queryset的延迟加载。事实上,它很可能生成多个DB查询(尽管还没有测试过)。此外,您最终得到的是一个普通的python列表,而不是一个queryset,因此不可能进行更多的过滤。

#2


3  

See Ordering by the order of values in a SQL IN() clause - you'd need to drop down to a raw queryset and it'd be database specific.

请参见SQL in()子句中的值的顺序排序—您需要将其降至原始的queryset,并且它是特定于数据库的。

If you're using MySQL for example you should be able to do a

举个例子,如果你使用MySQL,你应该可以做一个

Model.objects.raw('select * from myapp_model where id in (3,1,8) order by field(id,3,1,8)')

#3


2  

Most of your sorting options assume there is an order to what you are sorting. If you can define the order you can use order_by and a field on your model, or sorted using python. If you want to just reorder things (with seemingly no logic) you could still probably use sorted:

大多数排序选项都假定排序是有顺序的。如果您可以定义您可以在模型上使用order_by和一个字段的顺序,或者使用python进行排序。如果你只是想要重新排序(看起来没有逻辑),你仍然可以使用排序:

for id in [3,1,8]:
    sorted(qs, key=lambda x: x.id == id)

#4


1  

Maybe you can use order-by as zeekay mentioned.

也许你可以像zeekay提到的那样使用order-by。

If it is OK that your QuerSet will be turned into a list, then you can use something like this

如果可以将您的QuerSet转换为列表,那么您可以使用如下内容

sorted(queryset, key=lambda x: x.id) 

#5


1  

Thank you all for your answers. I'v came up with another solution. It's not the best one but is only needs to do one query to the database. I have a list with the id's I want ordered by my needs. Then I make the query and fill in a dictionary with the data and finally I traverse l picking up the objects in an ordered fashion.

谢谢大家的回答。我想到了另一个解决办法。它不是最好的,但只需要对数据库执行一个查询。我有一张清单,上面有我需要的id。然后我进行查询,并用数据填充字典,最后以有序的方式遍历对象。

l =[7,1,4]
p_dict = {}
p = Poi.objects.filter(id__in=l)
for i in p:
    p_dict[i.id] = i

Using this I will use a lot of memory right? But I gain in accesses to the database.

用这个我会用到很多内存,对吧?但是我获得了对数据库的访问。

@a-lee I will investigate your solution and try to tranform it to postgresql.

@a-lee我将研究您的解决方案并尝试将其转换为postgresql。

#6


0  

Um, I don't know if this has just been changed really recently or something (this has definitely been the case since at least August), but you can query using exactly the OP's syntax....

嗯,我不知道如果这真的刚刚改变了最近什么的(这无疑是至少自8月以来),但是您可以查询使用完全OP的语法....

#1


5  

No. There is no way to do what you want short of some contrived mechanism like:

不。没有办法去做你想做的,缺少一些人为的机制:

qs = m.objects.filter(id__in=[3,1,8])
qs_sorted = list()
for id in [3,1,8]:
    qs_sorted.append(qs.get(id=id))

You'd need to throw some exception handling in there as well, just in case one of the specified ids wasn't actually returned.

您还需要在其中抛出一些异常处理,以防指定的id实际上没有返回。

The negatives are that this will effectively negate the lazy loading of queryset. In fact, it's very likely to generate multiple DB queries (haven't tested that though). Also, you end up with a normal python list instead of a queryset, so no more filtering is possible.

缺点是这将有效地消除queryset的延迟加载。事实上,它很可能生成多个DB查询(尽管还没有测试过)。此外,您最终得到的是一个普通的python列表,而不是一个queryset,因此不可能进行更多的过滤。

#2


3  

See Ordering by the order of values in a SQL IN() clause - you'd need to drop down to a raw queryset and it'd be database specific.

请参见SQL in()子句中的值的顺序排序—您需要将其降至原始的queryset,并且它是特定于数据库的。

If you're using MySQL for example you should be able to do a

举个例子,如果你使用MySQL,你应该可以做一个

Model.objects.raw('select * from myapp_model where id in (3,1,8) order by field(id,3,1,8)')

#3


2  

Most of your sorting options assume there is an order to what you are sorting. If you can define the order you can use order_by and a field on your model, or sorted using python. If you want to just reorder things (with seemingly no logic) you could still probably use sorted:

大多数排序选项都假定排序是有顺序的。如果您可以定义您可以在模型上使用order_by和一个字段的顺序,或者使用python进行排序。如果你只是想要重新排序(看起来没有逻辑),你仍然可以使用排序:

for id in [3,1,8]:
    sorted(qs, key=lambda x: x.id == id)

#4


1  

Maybe you can use order-by as zeekay mentioned.

也许你可以像zeekay提到的那样使用order-by。

If it is OK that your QuerSet will be turned into a list, then you can use something like this

如果可以将您的QuerSet转换为列表,那么您可以使用如下内容

sorted(queryset, key=lambda x: x.id) 

#5


1  

Thank you all for your answers. I'v came up with another solution. It's not the best one but is only needs to do one query to the database. I have a list with the id's I want ordered by my needs. Then I make the query and fill in a dictionary with the data and finally I traverse l picking up the objects in an ordered fashion.

谢谢大家的回答。我想到了另一个解决办法。它不是最好的,但只需要对数据库执行一个查询。我有一张清单,上面有我需要的id。然后我进行查询,并用数据填充字典,最后以有序的方式遍历对象。

l =[7,1,4]
p_dict = {}
p = Poi.objects.filter(id__in=l)
for i in p:
    p_dict[i.id] = i

Using this I will use a lot of memory right? But I gain in accesses to the database.

用这个我会用到很多内存,对吧?但是我获得了对数据库的访问。

@a-lee I will investigate your solution and try to tranform it to postgresql.

@a-lee我将研究您的解决方案并尝试将其转换为postgresql。

#6


0  

Um, I don't know if this has just been changed really recently or something (this has definitely been the case since at least August), but you can query using exactly the OP's syntax....

嗯,我不知道如果这真的刚刚改变了最近什么的(这无疑是至少自8月以来),但是您可以查询使用完全OP的语法....