2009-04-15 77 views
1

我有一个模型,在其Meta类下有一个排序字段。当我执行查询并取回模型的QuerySet时,它按指定的顺序。但是,如果我有列表中的此模型的实例并在列表上执行排序方法,那么顺序与我想要的顺序不同。有没有办法对模型的实例列表进行排序,使得顺序与模型定义中指定的顺序相同?如何以相同的方式订购列表QuerySets在Django中订购?

回答

3

不是自动的,但有一些工作,是的。您需要定义一个比较器函数(或模型类上的方法),以便根据相关属性比较两个模型实例。例如:对卡尔的回答

class Dated(models.Model): 
    ... 
    created = models.DateTimeField(default=datetime.now) 

    class Meta: 
    ordering = ('created',) 

    def __cmp__(self, other): 
    try: 
     return cmp(self.created, other.created) 
    except AttributeError: 
     return cmp(self.created, other) 
+0

+1很好的解决方案,可以在模型级别保持排序,因此无论列表排序完成的位置如何,它都可以被透明地遵守。 – 2009-04-16 13:54:58

3

您的问题的答案是不同程度的是,有一些手动要求。如果list你的意思是已经被一些复杂的查询形成,那么,肯定有queryset

queryset.order_by(ClassName.Meta.ordering) 

queryset.order_by(instance._meta.ordering) 

queryset.order_by("fieldname") #If you like being manual 

如果你不工作一个查询集,那么当然你仍然可以排序,就像任何人在Python中排序复杂对象一样:

  • 比较
  • 指定键
  • 装饰/排序/去除装饰

See the python wiki for a detailed explanation of all three.

2

大厦,你可以很容易地添加使用的所有排序字段,甚至检测是按照相反的顺序者的能力。

class Person(models.Model): 
    first_name = models.CharField(max_length=50) 
    last_name = models.CharField(max_length=50) 
    birthday = date = models.DateField() 

    class Meta: 
    ordering = ['last_name', 'first_name'] 

    def __cmp__(self, other): 
    for order in self._meta.ordering: 
     if order.startswith('-'): 
     order = order[1:] 
     mode = -1 
     else: 
     mode = 1 
     if hasattr(self, order) and hasattr(other, order): 
     result = mode * cmp(getattr(self, order), getattr(other, order)) 
     if result: return result 
    return 0 
+0

非常好。最好把它放到`models.Model`的子类中,这样你就可以在整个模型中使用它。 – Tom 2011-02-02 11:56:16