模型的元數據Meta -- Django從入門到精通系列教程

該系列教程系我的原創,並完整發布在我的官網劉江的博客和教程

全部轉載本文者,需在頂部顯著位置註明原做者及www.liujiangblog.com官網地址。


模型的元數據,指的是「除了字段外的全部內容」,例如排序方式、數據庫表名、人類可讀的單數或者複數名等等。全部的這些都是非必須的,甚至元數據自己對模型也是非必須的。可是,我要說可是,有些元數據選項能給予你極大的幫助,在實際使用中具備重要的做用,是實際應用的‘必須’。python

想在模型中增長元數據,方法很簡單,在模型類中添加一個子類,名字是固定的Meta,而後在這個Meta類下面增長各類元數據選項或者說設置項。參考下面的例子:mysql

from django.db import models

class Ox(models.Model):
    horn_length = models.IntegerField()

    class Meta:         # 注意,是模型的子類,要縮進!
        ordering = ["horn_length"]
        verbose_name_plural = "oxen"

上面的例子中,咱們爲模型Ox增長了兩個元數據‘ordering’和‘verbose_name_plural’,分別表示排序和複數名,下面咱們會詳細介紹有哪些可用的元數據選項。算法

強調:每一個模型均可以有本身的元數據類,每一個元數據類也只對本身所在模型起做用。sql


abstract

若是abstract=True,那麼模型會被認爲是一個抽象模型。抽象模型自己不實際生成數據庫表,而是做爲其它模型的父類,被繼承使用。具體內容能夠參考Django模型的繼承。數據庫


app_label

若是定義了模型的app沒有在INSTALLED_APPS中註冊,則必須經過此元選項聲明它屬於哪一個app,例如:django

app_label = 'myapp'

base_manager_name

自定義模型的_base_manager管理器的名字。模型管理器是Django爲模型提供的API所在。Django1.10新增。oracle


db_table

指定在數據庫中,當前模型生成的數據表的表名。好比:app

db_table = 'my_freinds'

友情建議:使用MySQL數據庫時,db_table用小寫英文。post


db_tablespace

自定義數據庫表空間的名字。默認值是工程的DEFAULT_TABLESPACE設置。ui


default_manager_name

自定義模型的_default_manager管理器的名字。Django1.10新增。


默認狀況下,從一個模型反向關聯設置有關係字段的源模型,咱們使用<model_name>_set,也就是源模型的名字+下劃線+set

這個元數據選項可讓你自定義反向關係名,同時也影響反向查詢關係名!看下面的例子:

from django.db import models

class Foo(models.Model):
    pass

class Bar(models.Model):
    foo = models.ForeignKey(Foo)

    class Meta:
        default_related_name = 'bars'   # 關鍵在這裏

具體的使用差異以下:

>>> bar = Bar.objects.get(pk=1)
>>> # 不能再使用"bar"做爲反向查詢的關鍵字了。
>>> Foo.objects.get(bar=bar)
>>> # 而要使用你本身定義的"bars"了。
>>> Foo.objects.get(bars=bar)

get_latest_by

Django管理器給咱們提供有latest()和earliest()方法,分別表示獲取最近一個和最前一個數據對象。可是,如何來判斷最近一個和最前面一個呢?也就是根據什麼來排序呢?

get_latest_by元數據選項幫你解決這個問題,它能夠指定一個相似 DateFieldDateTimeField或者IntegerField這種能夠排序的字段,做爲latest()和earliest()方法的排序依據,從而得出最近一個或最前面一個對象。例如:

get_latest_by = "order_date"

managed

該元數據默認值爲True,表示Django將按照既定的規則,管理數據庫表的生命週期。

若是設置爲False,將不會針對當前模型建立和刪除數據庫表。在某些場景下,這可能有用,但更多時候,你能夠忘記該選項。


order_with_respect_to

這個選項很差理解。其用途是根據指定的字段進行排序,一般用於關係字段。看下面的例子:

from django.db import models

class Question(models.Model):
    text = models.TextField()
    # ...

class Answer(models.Model):
    question = models.ForeignKey(Question, on_delete=models.CASCADE)
    # ...

    class Meta:
        order_with_respect_to = 'question'

上面在Answer模型中設置了order_with_respect_to = 'question',這樣的話,Django會自動提供兩個API,get_RELATED_order()set_RELATED_order(),其中的RELATED用小寫的模型名代替。假設如今有一個Question對象,它關聯着多個Answer對象,下面的操做返回包含關聯的Anser對象的主鍵的列表[1,2,3]:

>>> question = Question.objects.get(id=1)
>>> question.get_answer_order()
[1, 2, 3]

咱們能夠經過set_RELATED_order()方法,指定上面這個列表的順序:

>>> question.set_answer_order([3, 1, 2])

一樣的,關聯的對象也得到了兩個方法get_next_in_order()get_previous_in_order(),用於經過特定的順序訪問對象,以下所示:

>>> answer = Answer.objects.get(id=2)
>>> answer.get_next_in_order()
<Answer: 3>
>>> answer.get_previous_in_order()
<Answer: 1>

這個元數據的做用......還沒用過,囧。


ordering

最經常使用的元數據之一了!

用於指定該模型生成的全部對象的排序方式,接收一個字段名組成的元組或列表。默認按升序排列,若是在字段名前加上字符「-」則表示按降序排列,若是使用字符問號「?」表示隨機排列。請看下面的例子:

ordering = ['pub_date']             # 表示按'pub_date'字段進行升序排列
ordering = ['-pub_date']            # 表示按'pub_date'字段進行降序排列
ordering = ['-pub_date', 'author']  # 表示先按'pub_date'字段進行降序排列,再按`author`字段進行升序排列。

permissions

該元數據用於當建立對象時增長額外的權限。它接收一個全部元素都是二元元組的列表或元組,每一個元素都是(權限代碼, 直觀的權限名稱)的格式。好比下面的例子:

permissions = (("can_deliver_pizzas", "能夠送披薩"),)

default_permissions

Django默認給全部的模型設置('add', 'change', 'delete')的權限,也就是增刪改。你能夠自定義這個選項,好比設置爲一個空列表,表示你不須要默認的權限,可是這一操做必須在執行migrate命令以前。


proxy

若是設置了proxy = True,表示使用代理模式的模型繼承方式。具體內容與abstract選項同樣,參考模型繼承章節。


required_db_features

聲明模型依賴的數據庫功能。好比['gis_enabled'],表示模型的創建依賴GIS功能。


required_db_vendor

聲明模型支持的數據庫。Django默認支持sqlite, postgresql, mysql, oracle


select_on_save

決定是否使用1.6版本以前的django.db.models.Model.save()算法保存對象。默認值爲False。這個選項咱們一般不用關心。


indexes

Django1.11新增的選項。

接收一個應用在當前模型上的索引列表,以下例所示:

from django.db import models

class Customer(models.Model):
    first_name = models.CharField(max_length=100)
    last_name = models.CharField(max_length=100)

    class Meta:
        indexes = [
            models.Index(fields=['last_name', 'first_name']),
            models.Index(fields=['first_name'], name='first_name_idx'),
        ]

unique_together

這個元數據是很是重要的一個!它等同於數據庫的聯合約束!

舉個例子,假設有一張用戶表,保存有用戶的姓名、出生日期、性別和籍貫等等信息。要求是全部的用戶惟一不重複,可如今有好幾個叫「張偉」的,如何區別它們呢?(不要和我說主鍵惟一,這裏討論的不是這個問題)

咱們能夠設置不能有兩個用戶在同一個地方同一時刻出生而且都叫「張偉」,使用這種聯合約束,保證數據庫能不能重複添加用戶(也不要和我談小几率問題)。在Django的模型中,如何實現這種約束呢?

使用unique_together,也就是聯合惟一!

好比:

unique_together = (('name', 'birth_day', 'address'),)

這樣,哪怕有兩個在同一天出生的張偉,但他們的籍貫不一樣,也就是兩個不一樣的用戶。一旦三者都相同,則會被Django拒絕建立。這一元數據常常被用在admin後臺,而且強制應用於數據庫層面。

unique_together接收一個二維的元組((xx,xx,xx,...),(),(),()...),每個元素都是一個元組,表示一組聯合惟一約束,能夠同時設置多組約束。爲了方便,對於只有一組約束的狀況下,能夠簡單地使用一維元素,例如:

unique_together = ('name', 'birth_day', 'address')

聯合惟一沒法做用於普通的多對多字段。


index_together

即將廢棄,使用index元數據代替。


verbose_name

最經常使用的元數據之一!用於設置模型對象的直觀、人類可讀的名稱。能夠用中文。例如:

verbose_name = "story"
verbose_name = "披薩"

若是你不指定它,那麼Django會使用小寫的模型名做爲默認值。


verbose_name_plural

英語有單數和複數形式。這個就是模型對象的複數名,好比「apples」。由於咱們中文一般不區分單複數,因此保持和verbose_name一致也能夠。

verbose_name_plural = "stories"
verbose_name_plural = "披薩"

若是不指定該選項,那麼默認的複數名字是verbose_name加上‘s’


label

前面介紹的元數據都是可修改和設置的,但還有兩個只讀的元數據,label就是其中之一。

label等同於app_label.object_name。例如polls.Question,polls是應用名,Question是模型名。


label_lower

同上,不過是小寫的模型名。

相關文章
相關標籤/搜索