2011-04-30 64 views
1

我想根据QuerySet中的对象如何评估为字符串来对我的QuerySet进行排序。Django QuerySet order_by字符串评估

所以我的模型看起来是这样的:

class System(models.Model): 
    operating_system = models.CharField(...) 
    language = models.CharField(...) 
    locale = models.CharField(...) 

    def __unicode__(self): 
    def __clean(orig, new): 
     if orig is None or orig == "": 
     if new is None or new == "": 
      return "" 
     else: 
      return str(new) 
     else: 
     if new is None or new == "": 
      return str(orig) 
     else: 
      return str(orig) + " " + str(new) 
    name = None 
    for attr in System._meta.fields: 
     if attr.name != "id": 
     name = __clean(name, getattr(self, attr.name)) 
    for m2mfield in System._meta.many_to_many: 
     for object in getattr(self, m2mfield.name).all(): 
     name = __clean(name, object) 

    if name == "": 
     return "Undefined" 
    return name 

而且,我希望能够做一个查询是这样的:

System.objects.filter(...).order_by('__unicode__') 

我不知道是否有一种方法在没有自定义管理器的情况下这样做

谢谢!

+0

你甚至不能用*自定义管理器来做它。 – 2011-04-30 03:55:39

+1

而不是那个骇客,你会考虑保存一个非规范化的字段是字符串值吗?我的意思是在你的系统模型上抛出另一个字段,并根据需要更新它,也许通过重写save(),然后你可以通过这个其他字段来排序... – Henry 2011-04-30 03:57:00

+0

@Henry你能否详细说明非规范化字段与字段的区别我目前使用的是(或给我一个指针?)谢谢。这绝对可行。虽然,感觉有点浪费空间? – 2011-05-02 14:39:13

回答

1

__unicode__您最终会得到一个表示System对象的单个字符串。而不是每次需要时计算它,计算一次并保存到模型中。现在

class System(models.Model): 
    operating_system = models.CharField(...) 
    language = models.CharField(...) 
    locale= models.CharField(...) 
    name = models.CharField(editable=False, ...) 

    def save(self, *args, **kwargs): 
     self.name = self._calculate_name() 
     super(System, self).save(*args, **kwargs) 

    def __unicode__(self): 
     return self.name 

    def _calculate_name(self): 
     # all that string manipulation and relationship stuff 

你可以通过这个名字轻松订购

System.objects.filter(...).order_by('name') 

有一些注意事项,以这种方法,它实际上取决于系统的使用。另外,不要担心空间,这是我的意见!


扩展在告诫

由于此字段“规格化”,它从同一个问题的其他关系数据是不是规范化的面部受损。 Denormalization可以引入更新异常(如果更改通过除System模型的save()方法之外的其他路由发生,则name依赖于的字段或关系可以更改而不更改为name,也可以减慢写入速度(在这种情况下可能会减慢写入少量),它可以增加空间需求(在我看来这里再也没有问题了),以及谷歌很乐意告诉你的其他东西,我敢肯定。请注意,在任何时候都应更新.name,因此,请仔细考虑在“清理”代码的哪些条件下会产生不同的结果。例如,如果您有一个OS表格,您可以在不触摸系统的情况下更改操作系统的说明表, ñ你必须认识到你的.name不会被保存到操作系统更新,它需要重新计算。有一些机制可以帮助像这样的信号,并覆盖更多的方法save()。您也可以根据需要批量更新它们。

这真的很大程度上取决于你的用例,这里没有详细说明。如果您更全面地展示您的用例,那么您可以帮助您缩小最佳解决方案的范围。

+0

谢谢亨利!这可能会做到这一点。你能简要地介绍一下这种方法的注意事项吗? – 2011-05-02 18:19:32