2011-04-30 45 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