2011-12-27 40 views
7

我發現在分類models.manager對象和覆蓋get_query_set方法或簡單地在子類中創建新方法和使用該方法方面沒有區別。因爲我以Django書爲例,subclassing models.Manager

class MaleManager(models.Manager): 
    def get_query_set(self): 
     return super(MaleManager, self).get_query_set().filter(sex='M') 
class FemaleManager(models.Manager): 
    def get_query_set(self): 
     return super(FemaleManager, self).get_query_set().filter(sex='F') 
class Person(models.Model): 
    first_name = models.CharField(max_length=50) 
    last_name = models.CharField(max_length=50) 
    sex = models.CharField(max_length=1, choices=(('M', 'Male'), ('F', 'Female'))) 
    people = models.Manager() 
    men = MaleManager() 
    women = FemaleManager() 

有了這個我可以使用; Person.women.all()Person.men.all()取出所有的男性或女性模型對象。但是,我想通過簡單的做法就可以實現類似的事情,而不會重寫get_query_set方法;

class MaleManager(models.Manager): 
    def get_male(self): 
     return self.filter(sex='M') 
class FemaleManager(models.Manager): 
    def get_female(self): 
     return return self.filter(sex='F') 
class Person(models.Model): 
    first_name = models.CharField(max_length=50) 
    last_name = models.CharField(max_length=50) 
    sex = models.CharField(max_length=1, choices=(('M', 'Male'), ('F', 'Female'))) 
    people = models.Manager() 
    men = MaleManager() 
    women = FemaleManager() 

現在,用這個,我可以用一點技巧來獲取所有這些對象; Person.objects.get_male()Person.objects.get_female()。但是,在如何獲取對象方面沒有任何細微的差別,但在第一種情況下可讀性和使用方面存在差異,而第二種情況更容易理解並且代碼較少。它們是否在編碼和編碼方面有重大差異模式?另一件事與第二個,如果我把兩個方法放在同一個類裏面,

class PeopleManager(models.Manager): 
     def get_male(self): 
      return self.filter(sex='M') 
     def get_female(self): 
      return return self.filter(sex='F') 
+1

如果你只有2種方法,由具有完全獨立的經理提供的組織是不值得的麻煩 - 不知道爲什麼Django的書會建議一個FemaleManager和MaleManager,而不是一個get_females和get_males方法在一個單一的經理。 –

+1

它更依賴於你的抽象層。如果你打算有'人員管理器',它只是按性別區分人的第二選項更有用。如果將來例如'FemaleManager'會有像get_blondes()或get_married()這樣的方法,那麼第二種方法更適合。 –

回答

4
  1. 通常你不想對模型的幾個經理。最好擴展默認管理器。

    class PeopleManager(models.Manager): 
        def get_male(self): 
         return self.filter(sex='M') 
    
        def get_female(self): 
         return return self.filter(sex='F') 
    
    class Person(models.Model): 
        .... 
        objects = PeopleManager() 
    

    然後,你將能夠使用Person.objects.get_male()Person.objects.get_female()和內置的方法,比如Person.objects.order_by()。例如,您可以查看django.contrib.auth.models中的自定義管理器。

  2. get_query_set有利於繼承。例如,你可以定義

    class SmithManager(PeopleManager): 
        def get_queryset(self): 
         return super(SmithManager, self).get_query_set().filter(last_name='Smith') 
    

    和經理的所有方法將只返回史密斯(Person.objects.get_male()將僅返回名爲史密斯等男性)。而且你不需要重寫所有的方法。

+1

在這種情況下,在你的第二點,我想這取決於我如何實例化模型中的對象。如果假設我做objects = models.Manager()和person = SmithManager()。然後,我可以使用默認對象和我繼承的自定義。 – Sandeep

+1

@瘋狂-36沒有任何理由不擴展默認管理器?有幾位管理人員的代碼不太清楚,難以維護。好建議:暫時忘記管理者。只需使用普通的「對象」來創建您的視圖,表單和其他內容。然後分析使用情況,並創建一個好的DRY經理來解決*你的任務*。這將是最好的經理。 – DrTyrsa

+1

謝謝,這個話題很有意思,所以我花了一段時間回顧一下。我現在就開始吧。 – Sandeep