Django中的自定义排序

41 投票
4 回答
36460 浏览
提问于 2025-04-15 11:42

在Django中,如何定义一个特定的排序方式呢?

具体来说,如果我有一个这样的查询集:['a10', 'a1', 'a2']

使用普通的排序方法(比如用Whatever.objects.order_by('someField'))会得到['a1', 'a10', 'a2'],但我想要的结果是:['a1', 'a2', 'a10']

那么,怎样才能正确地定义我自己的排序方式呢?

4 个回答

1

这要看你想在哪里使用它。

如果你想在自己的模板里用它,我建议你写一个模板标签,这样可以帮你进行排序。在这个标签里,你可以使用任何你想要的排序算法。

在管理后台,我通过扩展模板来满足我的需求,并加载上面提到的模板标签来进行自定义排序。

40

@Jarret的回答(在Python中进行排序)对于简单的情况非常有效。但是,一旦你有了一个很大的表格,并且想要,比如说,只提取按特定方式排序的第一页结果,这种方法就不太管用了(你必须先从数据库中提取每一行数据,才能进行排序)。在这种情况下,我会考虑添加一个去规范化的“排序”字段,这个字段在保存数据时从“名称”字段中填充,这样你就可以在数据库层面上按照通常的方式进行排序。

50

据我所知,数据库这边并没有办法像这样指定排序,因为这会太依赖于具体的后端技术。如果你需要排序的话,可以使用传统的Python排序方法:

class Foo(models.Model):
    name = models.CharField(max_length=128)

Foo.objects.create(name='a10')
Foo.objects.create(name='a1')
Foo.objects.create(name='a2')

ordered = sorted(Foo.objects.all(), key=lambda n: (n[0], int(n[1:])))
print ordered # yields a1, a2, 10

如果你发现自己经常需要这种排序,我建议你为你的模型创建一个自定义的 models.Manager 子类来处理排序。可以像这样做:

class FooManager(models.Manager):
    def in_a_number_order(self, *args, **kwargs):
        qs = self.get_query_set().filter(*args, **kwargs)
        return sorted(qs, key=lambda n: (n[0], int(n[1:])))

class Foo(models.Model):
    ... as before ...
    objects = FooManager()

print Foo.objects.in_a_number_order()
print Foo.objects.in_a_number_order(id__in=[5, 4, 3]) # or any filtering expression

撰写回答