欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Django中自定義模型管理器(Manager)及方法

 更新時間:2019年09月23日 13:12:06   作者:迎風(fēng)而來  
這篇文章主要介紹了Django中自定義模型管理器(Manager)及方法,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價值,需要的朋友可以參考下

1.自定義管理器(Manager)

在語句Book.objects.all()中, objects 是一個特殊的屬性,通過它來查詢數(shù)據(jù)庫,它就是模型的一個Manager.

每個Django模型至少有一個manager,你可以創(chuàng)建自定義manager以定制數(shù)據(jù)庫的訪問.

這里有兩個方法創(chuàng)建自定義manager:添加額外的manager;修改manager返回的初始Queryset.

添加額外的manager

增加額外的manager是為模塊添加 表級功能 的首選辦法.(至于 行級功能 ,也就是只作用于模型實例對象的函數(shù),則通過自定義模型方法實現(xiàn)).

例如,為Book模型添加一個 title_count() 的manger方法,它接收一個 keyword ,并返回標(biāo)題中包含 keyword 的書的數(shù)量.

from django.db import models
# 自定義模型管理器類
class BookManager(models.Manager):
  #自定義模型管理器中的方法
  def title_count(self, keyword):
    return self.filter(title_icountains=keyword).count()
class Book(models.Model):
  title = models.CharField(max_length=100)
  authors = models.ManyToManyField(Author)
  ...
  objects = BookManager()
  def __str__(self):
    return self.title

1.我們創(chuàng)建一個BookManager類,繼承自 django.db.models.Manager .它只有一個方法 title_count() ,來進(jìn)行統(tǒng)計.注意,這個方法使用了 self.filter() ,這個self指manager本身.

2.將BookManager()賦值給模型的objects屬性.它將取代模型的默認(rèn)manager(objects).把它命名為objects是為了與默認(rèn)的manager保持一致.

現(xiàn)在我們可以進(jìn)行下面的操作:

>>> Books.objects.title_count('django')  #這是我們自定義的manager中的查詢方法

>>> Books.objects.filter(title__icontains='django').count()  # 默認(rèn)的查詢方法依然可用

這樣我們可以將經(jīng)常使用的查詢進(jìn)行封裝,就不必重復(fù)寫代碼了.

修改初始Manager Queryset

manager的基礎(chǔ)Queryset返回系統(tǒng)中的所有對象.例如, Book.objects.all() 返回book數(shù)據(jù)庫中的所有書籍.你而已通過覆蓋 Manager.get_queryset() 方法來重寫manager的基礎(chǔ)Queryset. get_queryset() 應(yīng)該按照你的需求返回一個Queryset.

例如,下面的模型有兩個manger--一個返回所有對象,另一個僅返回作者是Roald Dahl的書

from django.db import models

#首先,定義一個Manager的子類
class DahlBookManager(models.Manager):
  def get_queryset(self):
    return super(DahlBookManager, self).get_queryset().filter(author='Roald Dahl')


# 然后,將它顯式地插入到Book模型中
class Book(models.Model):
  title = models.CharField(max_length=100)
  author = models.CharField(max_length=50)
  ...
  objects = models.Manager()  # 默認(rèn)Manager
  dahl_objects = DahlBookManager()  # 自定義的特殊Manager

在這個示例模型中, Book.objects.all() 將返回數(shù)據(jù)庫中的所有書籍,而 Book.dahl_objects.all() 只返回作者是Roald Dahl的書籍.注意我們明確的將 objects 設(shè)置為默認(rèn) Manger 的一個實例,因為如果我們不這樣做,那么dahl_objects將成為唯一一個可用的manager.

由于 get_queryset() 返回一個Queryset對象,所以你可以使用 filter() , exclude() 和其他所有的Queryset方法.

如果你使用自定義的Manager對象,請注意,Django遇到的第一個Manager(以它在模型中被定義的位置為準(zhǔn))會有一個特殊狀態(tài)。 Django將會把第一個Manager 定義為默認(rèn)Manager ,Django的許多部分(但是不包括admin應(yīng)用)將會明確地為模型使用這個manager。 結(jié)論是,你應(yīng)該小心地選擇你的默認(rèn)manager。因為覆蓋 get_queryset() 了,你可能接受到一個無用的返回對像,你必須避免這種情況.

2.自定義模型方法

為了給你的對像添加一個行級功能,那就定義一個自定義方法.鑒于manager經(jīng)常被用來用一些整表操作(table-wide).模型方法應(yīng)該只對特殊模型實例起作用.

from django.db import models

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

  def baby_boomer_status(self):
    # Returns the person's baby_boomer status
    import datetime
    if self.birth_date < datetime.date(1945, 8, 1):
      return 'Pre-boomer'
    elif self.birth_date < datetime.date(1965, 1, 1):
      return 'Baby boomer'
    else:
      return 'Post-boomer'

  def _get_full_name(self):
    # Return the person's full name
    return f'{self.first_name} {self.last_name}'
  full_name = property(_get_full_name)  # 將類方法包裝為屬性

這些方法的使用:

>>> p = Person.objects.get(first_name='Barack', last_name='Obama')
>>> p.birth_date
datetime.date(1961, 8, 4)
>>> p.baby_boomer_status()
'Baby boomer'
>>> p.full_name # 注意這不是一個方法 -- 它被視為一個屬性
'Barack Obama'

3.重寫預(yù)定義的模型方法

還有一組模型方法了封裝了一些你可能想要自定義的數(shù)據(jù)庫行為.特別是你可能想要修改 save() 和 delete() 的工作方式.你可以自由的重寫這些方法(以及其他的模型方法)來改變行為.重寫內(nèi)置方法的經(jīng)典用例就是你想要在保存一個對象是做些其他的什么.例如:

from django.db import models

class Blog(models.Model):
  name = models.CharField(max_length=100)
  tagline = models.TextField()

  def save(self, *args, **kwargs):
    do_something()
    super(Blog, self).save(*args, **kwargs)  #Call the "real" save() method.
    do_something_else()

你也可以阻止保存行為:

from django.db import models
class Blog(models.Model):
  name = models.CharField(max_length=100)
  tagline = models.TextField()
  def save(self, *args, **kwargs):
    if self.name == 'Yoko Ono's Blog':
      return  # Yoko shall never have her own blog!
    else:
      super(Blog, self).save(*args, **kwargs)  #Call the "real" save() method

記住,繼承超類的方法非常重要,即 super(Blog, self).save(*args, **kwargs) ,它確保該對象仍被保存到數(shù)據(jù)庫中.如果你忘記調(diào)用超類方法,那么默認(rèn)的行為將不會發(fā)生,也不會發(fā)生數(shù)據(jù)庫操作.

同樣重要的是,您要傳遞可以傳遞給模型方法的參數(shù)——這就是 *args, **kwargs 所做的事情。Django將不時擴(kuò)展內(nèi)置模型方法的功能,并添加新的參數(shù)。如果您在方法定義中使用了 *args, **kwargs ,您將保證您的代碼在添加時將自動支持這些參數(shù)。

Model.clean()

應(yīng)用這個方法來提供自定義的模型驗證,以及修改模型的屬性.例如,你可以使用它來給一個字段自動提供值,或者用于多個字段需要一起驗證的情形:

import detetime
from django.core.exceptions import ValidationError
from django.db import models

class Article(models.Model):
  ...
  def clean(self):
    # Don't allow draft entries to have a pub_date
    if self.status == 'draft' and self.pub_date is not done:
      raise ValidationEroor('Draft entries may not have a publication date')
    #Set the pub_date for published items if it hasn't been set already
    if self.status == 'published' and self.pub_date is None:
      self.pub_date = datetime.date.today()

注意,調(diào)用模型的 save() 方法時,不會自動調(diào)用 clean() 方法,需要views手動調(diào)用.

上面的示例中, clean() 引發(fā)的ValidationError異常通過一個字符串實例化,所以它將被保存在一個特殊的錯誤字典中,鍵為 NON_FIELD_ERRORS .這個鍵用于整個模型出現(xiàn)的錯誤而不是一個特定字段穿線的錯誤:

from django.core.exceptions import ValidationError, NON_FIELD_ERRORS
try:
  article.full_clean()
except ValidationError as e:
  non_field_errors = e.message_dict[NON_FIELD_ERRORS]

若要引發(fā)一個特定字段的異常,可以使用一個字典實例化 ValidationError ,其中字典的鍵為字段名.我們可以更新前面的例子,只引發(fā) pub_date 字段上的異常:

class Article(models.Model):
  ...
  def clean(self):
    # Don't allow draft entries to have a pub_date.
    if self.status == 'draft' and self.pub_date is not None:
      raise ValidationError({'pub_date': 'Draft entries may not have a publication date.'})
    ...

總結(jié)

以上所述是小編給大家介紹的Django中自定義模型管理器(Manager)及方法,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復(fù)大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!
如果你覺得本文對你有幫助,歡迎轉(zhuǎn)載,煩請注明出處,謝謝!

相關(guān)文章

  • Python不同格式打印九九乘法表示例

    Python不同格式打印九九乘法表示例

    大家好,本篇文章主要講的是Python不同格式打印九九乘法表示例,感興趣的同學(xué)趕快來看一看吧,對你有幫助的話記得收藏一下哦,方便下次瀏覽
    2021-12-12
  • Tensorflow中的placeholder和feed_dict的使用

    Tensorflow中的placeholder和feed_dict的使用

    這篇文章主要介紹了Tensorflow中的placeholder和feed_dict的使用,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-07-07
  • Python PySpider爬蟲框架安裝使用教程

    Python PySpider爬蟲框架安裝使用教程

    PySpider是一個Python編寫的分布式網(wǎng)絡(luò)爬蟲框架,它可以幫助開發(fā)者快速構(gòu)建和部署爬蟲,并支持爬蟲任務(wù)的分布式運(yùn)行,PySpider基于Twisted網(wǎng)絡(luò)框架和MongoDB數(shù)據(jù)庫,具有高效、穩(wěn)定、易用等特點,同時還提供了一套Web界面,可以方便地查看爬蟲任務(wù)的運(yùn)行狀態(tài)和結(jié)果
    2023-11-11
  • Python 變量的創(chuàng)建過程詳解

    Python 變量的創(chuàng)建過程詳解

    這篇文章主要介紹了Python 變量的創(chuàng)建過程詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-09-09
  • Python3 獲取文件屬性的方式(時間、大小等)

    Python3 獲取文件屬性的方式(時間、大小等)

    這篇文章主要介紹了Python3 獲取文件屬性的方式(時間、大小等),具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-03-03
  • python3 實現(xiàn)對圖片進(jìn)行局部切割的方法

    python3 實現(xiàn)對圖片進(jìn)行局部切割的方法

    今天小編就為大家分享一篇python3 實現(xiàn)對圖片進(jìn)行局部切割的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-12-12
  • Linux下python3.7.0安裝教程

    Linux下python3.7.0安裝教程

    這篇文章主要為大家詳細(xì)介紹了Linux下python3.7.0安裝教程,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-07-07
  • 關(guān)于python selenium 運(yùn)行時彈出窗口問題

    關(guān)于python selenium 運(yùn)行時彈出窗口問題

    最近在做一個網(wǎng)頁代填項目,用到了python的selenium知識,經(jīng)過了各種嘗試與搜索最后終算是較完美的解決了,下面小編給大家?guī)砹藀ython selenium 運(yùn)行時彈出窗口問題,感興趣的朋友一起看看吧
    2021-11-11
  • 用Python寫一個自動木馬程序

    用Python寫一個自動木馬程序

    這篇文章主要介紹了用Python寫一個自動木馬程序的方法,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價值,需要的朋友可以參考下
    2019-09-09
  • Pytest單元測試框架生成HTML測試報告及優(yōu)化的步驟

    Pytest單元測試框架生成HTML測試報告及優(yōu)化的步驟

    本文主要介紹了Pytest單元測試框架生成HTML測試報告及優(yōu)化的步驟,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-01-01

最新評論