Django中的自定义排序
在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