Skip to main content
 首页 » 编程设计

python之以任意顺序对查询集进行排序

2025年05月04日23JeffreyZhao

我有这样一个模板来呈现来自数据库的 block

<div class="panel panel-default"> 
  <div class="panel-heading"> 
    <a style='font-size:18pt' href="article/list/{{ b.id }}">{{ b.name }}</a> 
    <span class='pull-right'>{{ b.admin }}</span> 
  </div> 
  <div class="panel-body"> 
    {{ b.desc }} 
  </div> 
</div> 

数据模型:

class Block(models.Model): 
    STATUS = ( 
        (1,  'normal'), 
        (0, 'deleted'), 
    ) 
    name = models.CharField("block name", max_length=100) 
    desc = models.CharField("block description", max_length=100) 
    admin = models.CharField("block admin", max_length=100) 
    status = models.IntegerField(choices=STATUS) 
 
    class Meta: 
        ordering = ("id",) 
 
    def __str__(self): 
        return self.name    

我检索数据为

In [2]: from article.models import Block 
In [3]: blocks = Block.objects.all() 
In [4]: blocks 
Out[4]: <QuerySet [<Block: Concepts>, <Block: Reading>, <Block: Coding>, <Block: Action>]> 

我想以 ['concept','code', 'read', 'action'] 的任意顺序呈现数据,而不是按 id,

通过观察,我发现这可以通过命令它的第二个字母来实现,

In [7]: sorted(l, key=lambda item: item[1], reverse=True) 
Out[7]: ['concept', 'code', 'read', 'action'] 

如何以这种方式对查询集进行排序?

请您参考如下方法:

您可以先注释每个 Block实例,然后按使用 Substr function [Django-doc] 的注释排序,比如:

from django.db.models.functions import <b>Substr</b> 
 
Block.objects.annotate( 
    sndchar=<b>Substr('name', 2, 1)</b> 
).order_by(<b>'-sndchar'</b>)

作为额外奖励每Block实例将有一个 sndchar name 的第二个字符属性属性(仅在此查询集中)。但我认为这不是真正的问题。如果它与另一列冲突,您可以重命名它。

<b>-</b>sndchar 中的减号字符意味着我们将按降序排序。如果你想按升序排序,你可以删除它。

因此这里的排序是在数据库级别完成的,这通常(显着)快于在 Django 级别执行此操作。

您还可以从第二个字符开始对字符串进行排序(这样在平局的情况下,第三个字符等被考虑在内),通过删除 length参数,因此用除第一个字符之外的名称进行注释:

from django.db.models.functions import Substr 
 
# This will sort on the third character in case of a tie, and so on 
Block.objects.annotate( 
    sndchar=<b>Substr('name', 2)</b> 
).order_by('-sndchar')