<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                <!-- 譯者:Github@wizardforcel --> # 管理器 # **class Manager** 管理器是一個接口,數據庫查詢操作通過它提供給django的模型。django應用的每個模型至少擁有一個 管理器。 管理器類的工作方式在 執行查詢文檔中闡述,而這篇文檔涉及了自定義管理器行為的模型選項。 ## 管理器的名字 ## 通常,django為每個模型類添加一個名為objects的管理器。然而,如果你想將objects用于字段名稱,或者你想使用其它名稱而不是objects訪問管理器,你可以在每個模型類中重命名它。在模型中定義一個值為models.Manager()的屬性,來重命名管理器。例如: ``` from django.db import models class Person(models.Model): #... people = models.Manager() ``` 使用例子中的模型, Person.objects會拋出AttributeError異常,而Person.people.all()會返回一個包含所有Person對象的列表。 ## 自定義管理器 ## 在一個特定的模型中,你可以通過繼承管理器類來構建一個自定義的管理器,以及實例化你的自定義管理器。 你有兩個原因可能會自己定義管理器:向器類中添加額外的方法,或者修改管理器最初返回的查詢集。 ### 添加額外的管理器方法 ### 為你的模型添加表級(table-level)功能時,采用添加額外的管理器方法是更好的處理方式。如果要添加行級功能--就是說該功能只對某個模型的實例對象起作用。在這種情況下,使用 模型方法 比使用自定義的管理器方法要更好。) 自定義的管理器 方法可以返回你想要的任何數據,而不只是查詢集。 例如,下面這個自定義的 管理器提供了一個 with_counts() 方法,它返回所有 OpinionPoll 對象的列表,而且列表中的每個對象都多了一個名為 num_responses的屬性,這個屬性保存一個聚合查詢(COUNT*)的結果: ``` from django.db import models class PollManager(models.Manager): def with_counts(self): from django.db import connection cursor = connection.cursor() cursor.execute(""" SELECT p.id, p.question, p.poll_date, COUNT(*) FROM polls_opinionpoll p, polls_response r WHERE p.id = r.poll_id GROUP BY p.id, p.question, p.poll_date ORDER BY p.poll_date DESC""") result_list = [] for row in cursor.fetchall(): p = self.model(id=row[0], question=row[1], poll_date=row[2]) p.num_responses = row[3] result_list.append(p) return result_list class OpinionPoll(models.Model): question = models.CharField(max_length=200) poll_date = models.DateField() objects = PollManager() class Response(models.Model): poll = models.ForeignKey(OpinionPoll) person_name = models.CharField(max_length=50) response = models.TextField() ``` 在這個例子中,你已經可以使用 OpinionPoll.objects.with_counts() 得到所有含有 num_responses屬性的 OpinionPoll對象。 這個例子要注意的一點是: 管理器方法可以訪問 self.model來得到它所用到的模型類。 ### 修改管理器初始的查詢集 ### 管理器自帶的 查詢集返回系統中所有的對象。例如,使用下面這個模型: ``` from django.db import models class Book(models.Model): title = models.CharField(max_length=100) author = models.CharField(max_length=50) ``` ... Book.objects.all() 語句將返回數據庫中所有的 Book 對象。 你可以通過重寫 Manager.get_queryset() 的方法來覆蓋 管理器自帶的 查詢集。get_queryset() 會根據你所需要的屬性返回 查詢集。 例如,下面的模型有兩個 管理器,一個返回所有的對象,另一個則只返回作者是 Roald Dahl 的對象: ``` # First, define the Manager subclass. class DahlBookManager(models.Manager): def get_queryset(self): return super(DahlBookManager, self).get_queryset().filter(author='Roald Dahl') # Then hook it into the Book model explicitly. class Book(models.Model): title = models.CharField(max_length=100) author = models.CharField(max_length=50) objects = models.Manager() # The default manager. dahl_objects = DahlBookManager() # The Dahl-specific manager. ``` 在這個簡單的例子中,Book.objects.all()將返回數據庫中所有的圖書。而 Book.dahl_objects.all() 只返回作者是 Roald Dahl 的圖書。 由于 get_queryset() 返回的是一個 查詢集 對象,所以你仍可以對它使用 filter(), exclude()和其他 查詢集的方法。所以下面這些例子都是可用的: ``` Book.dahl_objects.all() Book.dahl_objects.filter(title='Matilda') Book.dahl_objects.count() ``` 這個例子還展示了另外一個很有意思的技巧:在同一個模型中使用多個管理器。你可以隨你所意在一個模型里面添加多個 Manager() 實例。下面就用很簡單的方法,給模型添加通用過濾器: 例如: ``` class AuthorManager(models.Manager): def get_queryset(self): return super(AuthorManager, self).get_queryset().filter(role='A') class EditorManager(models.Manager): def get_queryset(self): return super(EditorManager, self).get_queryset().filter(role='E') class Person(models.Model): first_name = models.CharField(max_length=50) last_name = models.CharField(max_length=50) role = models.CharField(max_length=1, choices=(('A', _('Author')), ('E', _('Editor')))) people = models.Manager() authors = AuthorManager() editors = EditorManager() ``` 在這個例子中,你使用 Person.authors.all(), Person.editors.all(),以及 Person.people.all(), 都會得到和名稱相符的結果。 #### 默認管理器 #### 如果你使用了自定義 管理器對象,要注意 Django 中的第一個 管理器 (按照模型中出現的順序而定) 擁有特殊的地位。Django 會將模型中定義的管理器解釋為默認的 管理器,并且 Django 中的一部分應用(包括數據備份)會使用默認的管理器,除了前面那個模型。因此,要決定默認的管理器時,要小心謹慎,仔細考量,這樣才能避免重寫 get_queryset() 導致無法正確地獲得數據。 #### 使用管理器訪問關聯對象 #### 默認情況下,在訪問相關對象時(例如choice.poll),Django 并不使用相關對象的默認管理器,而是使用一個"樸素"管理器類的實例來訪問。這是因為 Django 要能從關聯對象中獲得數據,但這些數據有可能被默認管理器過濾掉,或是無法進行訪問。 如果普通的樸素管理器類(django.db.models.Manager)并不適用于你的應用,那么你可以通過在管理器類中設置 use_for_related_fields ,強制 Django 在你的模型中使用默認的管理器。這部分內容在 下面有 詳細介紹。 ### 調用自定義的查詢集 ### 雖然大多數標準查詢集的方法可以從管理器中直接訪問到,但是這是一個例子,訪問了定義在自定義 查詢集上的額外方法,如果你也在管理器上面實現了它們: ``` class PersonQuerySet(models.QuerySet): def authors(self): return self.filter(role='A') def editors(self): return self.filter(role='E') class PersonManager(models.Manager): def get_queryset(self): return PersonQuerySet(self.model, using=self._db) def authors(self): return self.get_queryset().authors() def editors(self): return self.get_queryset().editors() class Person(models.Model): first_name = models.CharField(max_length=50) last_name = models.CharField(max_length=50) role = models.CharField(max_length=1, choices=(('A', _('Author')), ('E', _('Editor')))) people = PersonManager() ``` 這個例子展示了如何直接從管理器 Person.people調用authors() 和 editors()。 ### 創建管理器 ### ** django 1.7 中新增 ** 對于上面的例子,同一個方法需要在查詢集 和 管理器上創建兩份副本,作為替代,QuerySet.as_manager()可以創建一個管理器的實例,它擁有自定義查詢集的方法: ``` class Person(models.Model): ... people = PersonQuerySet.as_manager() ``` 通過QuerySet.as_manager()創建的管理器 實例,實際上等價于上面例子中的PersonManager。 并不是每個查詢集的方法都在管理器層面上有意義。比如 QuerySet.delete(),我們有意防止它復制到管理器 中。 方法按照以下規則進行復制: + 公共方法默認被復制。 + 私有方法(前面帶一個下劃線)默認不被復制。 + 帶queryset_only 屬性,并且值為False的方法總是被復制。 + 帶 queryset_only 屬性,并且值為True 的方法不會被復制。 例如: ``` class CustomQuerySet(models.QuerySet): # Available on both Manager and QuerySet. def public_method(self): return # Available only on QuerySet. def _private_method(self): return # Available only on QuerySet. def opted_out_public_method(self): return opted_out_public_method.queryset_only = True # Available on both Manager and QuerySet. def _opted_in_private_method(self): return _opted_in_private_method.queryset_only = False ``` #### from_queryset #### ``` classmethod from_queryset(queryset_class) ``` 在進一步的使用中,你可能想創建一個自定義管理器和一個自定義查詢集。你可以調用Manager.from_queryset(),它會返回管理器的一個子類,帶有自定義查詢集所有方法的副本: ``` class BaseManager(models.Manager): def manager_only_method(self): return class CustomQuerySet(models.QuerySet): def manager_and_queryset_method(self): return class MyModel(models.Model): objects = BaseManager.from_queryset(CustomQueryset)() ``` 你也可以在一個變量中儲存生成的類: ``` CustomManager = BaseManager.from_queryset(CustomQueryset) class MyModel(models.Model): objects = CustomManager() ``` ### 自定義管理器和模型繼承 ### 類繼承和模型管理器兩者之間配合得并不是很好。 管理器一般只對其定義所在的類起作用,在子類中對其繼承絕對不是一個好主意。 而且,因為第一個 管理器會被 Djange 聲明為默認的管理器,所以對默認的管理器 進行控制是非常必要的。下面就是 Django 如何處理自定義管理器和模型繼承(model inheritance)的: + 定義在非抽象基類中的管理器是 不會 被子類繼承的。如果你想從一個非抽象基類中重用管理器,只能在子類中重定義管理器。 這是因為這種管理器與定義它的模型 綁定得非常緊密,所以繼承它們經常會導致異常的結果(特別是默認管理器運行的時候)。 因此,它們不應繼承給子類。 + 定義在抽象基類中的管理器總是被子類繼續的,是按 Python 的命名解析順序解析的(首先是子類中的命名覆蓋所有的,然后是第一個父類的,以此類推)。 抽象類用來提取子類中的公共信息和行為,定義公共管理器也是公共信息的一部分。 + 如果類當中顯示定義了默認管理器,Django 就會以此做為默認管理器;否則就會從第一個抽象基類中繼承默認管理器; 如果沒有顯式聲明默認管理器,那么 Django 就會自動添加默認管理器。 如果你想在一組模型上安裝一系列自定義管理器,上面提到的這些規則就已經為你的實現提供了必要的靈活性。你可以繼承一個抽象基類,但仍要自定義默認的管理器。例如,假設你的基類是這樣的: ``` class AbstractBase(models.Model): # ... objects = CustomManager() class Meta: abstract = True ``` 如果你在基類中沒有定義管理器,直接使用上面的代碼,默認管理器就是從基類中繼承的 objects: ``` class ChildA(AbstractBase): # ... # This class has CustomManager as the default manager. pass ``` 如果你想從 AbstractBase繼承,卻又想提供另一個默認管理器,那么你可以在子類中定義默認管理器: ``` class ChildB(AbstractBase): # ... # An explicit default manager. default_manager = OtherManager() ``` 在這個例子中, default_manager就是默認的 管理器。從基類中繼承的 objects 管理器仍是可用的。只不過它不再是默認管理器罷了。 最后再舉個例子,假設你想在子類中再添加一個額外的管理器,但是很想使用從 AbstractBase繼承的管理器做為默認管理器。那么,你不在直接在子類中添加新的管理器,否則就會覆蓋掉默認管理器,而且你必須對派生自這個基類的所有子類都顯示指定管理器。 解決辦法就是在另一個基類中添加新的管理器,然后繼承時將其放在默認管理器所在的基類 之后。例如: ``` class ExtraManager(models.Model): extra_manager = OtherManager() class Meta: abstract = True class ChildC(AbstractBase, ExtraManager): # ... # Default manager is CustomManager, but OtherManager is # also available via the "extra_manager" attribute. pass ``` 注意在抽象模型上面定義一個自定義管理器的時候,不能調用任何使用這個抽象模型的方法。就像: ``` ClassA.objects.do_something() ``` 是可以的,但是: ``` AbstractBase.objects.do_something() ``` 會拋出一個異常。這是因為,管理器被設計用來封裝對象集合管理的邏輯。由于抽象的對象中并沒有一個集合,管理它們是毫無意義的。如果你寫了應用在抽象模型上的功能,你應該把功能放到抽象模型的靜態方法,或者類的方法中。 ### 實現上的注意事項 ### 無論你向自定義管理器中添加了什么功能,都必須可以得到 管理器實例的一個淺表副本:例如,下面的代碼必須正常運行: ``` >>> import copy >>> manager = MyManager() >>> my_copy = copy.copy(manager) ``` Django 在一些查詢中會創建管理器的淺表副本;如果你的管理器不能被復制,查詢就會失敗。 這對于大多數自定義管理器不是什么大問題。如果你只是添加一些簡單的方法到你的管理器中,不太可能會把你的管理器實例變為不可復制的。但是,如果你覆蓋了\_\_getattr\_\_,或者其它管理器中控制對象狀態的私有方法,你應該確保不會影響到管理器的復制。 ## 控制自動管理器的類型 ## 這篇文檔已經提到了Django創建管理器類的一些位置:默認管理器和用于訪問關聯對象的“樸素” 管理器。在 Django 的實現中也有很多地方用到了臨時的樸素管理器。 正常情況下,django.db.models.Manager 類的實例會自動創建管理器。 在整個這一節中,我們將那種由 Django 為你創建的管理器稱之為 "自動管理器",既有因為沒有管理器而被 Django 自動添加的默認管理器, 也包括在訪問關聯模型時使用的臨時管理器。 有時,默認管理器也并非是自動管理器。 一個例子就是 Django 自帶的django.contrib.gis 應用,所有 gis模型都必須使用一個特殊的管理器類(GeoManager),因為它們需要運行特殊的查詢集(GeoQuerySet)與數據庫進行交互。這表明無論自動管理器是否被創建,那些要使用特殊的管理器的模型仍要使用這個特殊的管理器類。 Django 為自定義管理器的開發者提供了一種方式:無論開發的管理器類是不是默認的管理器,它都應該可以用做自動管理器。 可以通過在管理器類中設置 use_for_related_fields 屬性來做到這點: ``` class MyManager(models.Manager): use_for_related_fields = True # ... ``` 如果在模型中的默認 管理器(在這些情況中僅考慮默認管理器)中設置了這個屬性,那么無論它是否需要被自動創建,Django 都會自動使用它。否則 Django 就會使用 django.db.models.Manager. > 歷史回顧 > > 從它使用目的來看,這個屬性的名稱(use_for_related_fields)好象有點古怪。原本,這個屬性僅僅是用來控制訪問關聯字段的管理器的類型,這就是它名字的由來。 后來它的作用更加拓寬了,但是名稱一直未變。 因為要保證現在的代碼在 Django 以后的版本中仍可以正常工作(continue to work),這就是它名稱不變的原因。 ### 在自動管理器實例中編寫正確的管理器 ### 在上面的django.contrib.gis 已經提到了, use_for_related_fields這個特性是在需要返回一個自定義查詢集子類的管理器中使用的。要在你的管理器中提供這個功能,要注意以下幾點。 #### 不要在這種類型的管理器子類中過濾掉任何結果 #### 一個原因是自動管理器是用來訪問關聯模型 的對象。 在這種情況下,Django 必須要能看到相關模型的所有對象,所以才能根據關聯關系得到任何數據 。 如果你重寫了 get_queryset() 方法并且過濾掉了一些行數據,Django 將返回不正確的結果。不要這么做! 在 get_queryset()方法中過濾掉數據,會使得它所在的管理器不適于用做自動管理器。 #### 設置 use_for_related_fields #### use_for_related_fields屬性必須在管理器類中設置,而不是在類的 實例中設置。上面已經有例子展示如何正確地設置,下面這個例子就是一個錯誤的示范: ``` # BAD: Incorrect code class MyManager(models.Manager): # ... pass # Sets the attribute on an instance of MyManager. Django will # ignore this setting. mgr = MyManager() mgr.use_for_related_fields = True class MyModel(models.Model): # ... objects = mgr # End of incorrect code. ``` 你也不應該在模型中使用這個屬性之后,在類上改變它。這是因為在模型類被創建時,這個屬性值馬上就會被處理,而且隨后不會再讀取這個屬性值。 這節的第一個例子就是在第一次定義的時候在管理器上設置use_for_related_fields屬性,所有的代碼就工作得很好。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看