Django模型類Meta元數據詳解

簡介

使用內部的class Meta 定義模型的元數據,例如:python

from django.db import models

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

    class Meta:
        ordering = ["horn_length"]
        verbose_name_plural = "oxen"

模型元數據是「任何不是字段的數據」,好比排序選項(ordering),數據庫表名(db_table)或者人類可讀的單複數名稱(verbose_name 和verbose_name_plural)。在模型中添加class Meta是徹底可選的,全部選項都不是必須的。算法

可用的元選項

abstract

Options.abstract
若是 abstract = True, 就表示模型是 抽象基類 (abstract base class).數據庫

app_label

Options.app_label
若是一個模型位於標準的位置以外(應用的models.py 或models 包),該模型必須定義它屬於哪一個應用:django

app_label = 'myapp'
New in Django 1.7:
定義在應用的models 模塊之外的模型,再也不須要app_label。後端

db_table

Options.db_table
該模型所用的數據表的名稱:app

db_table = 'music_album'
爲節省你的時間,Django 會根據模型類的名稱和包含它的應用的名稱自動指定數據庫表名稱。一個模型的數據庫表名稱,由這個模型的「應用標籤」(在manage.py startapp中使用的名稱)和模型類名稱之間加上下劃線組成。測試

舉個例子,  bookstore應用(使用  manage.py startapp bookstore 建立),裏面有個名爲 Book的模型,那數據表的名稱就是  bookstore_book 。spa

使用 Meta類中的 db_table 參數來重寫數據表的名稱。設計

數據表名稱能夠是 SQL 保留字,也能夠包含不容許出如今 Python 變量中的特殊字符,這是由於 Django 會自動給列名和表名添加引號。代理

在 MySQL中使用小寫字母爲表命名

當你經過db_table覆寫表名稱時,強烈推薦使用小寫字母給表命名,特別是若是你用了MySQL做爲後端。詳見MySQL注意事項 。

Oracle中表名稱的引號處理

爲了聽從Oracle中30個字符的限制,以及一些常見的約定,Django會縮短表的名稱,並且會把它所有轉爲大寫。在db_table的值外面加上引號來避免這種狀況:

db_table = '"name_left_in_lowercase"'
這種帶引號的名稱也能夠用於Django所支持的其餘數據庫後端,可是除了Oracle,引號不起任何做用。詳見 Oracle 注意事項 。

db_tablespace

Options.db_tablespace
當前模型所使用的數據庫表空間 的名字。默認值是項目設置中的DEFAULT_TABLESPACE,若是它存在的話。若是後端並不支持表空間,這個選項能夠忽略。

default_related_name

Options.default_related_name
New in Django 1.8.
這個名字會默認被用於一個關聯對象到當前對象的關係。默認爲 <model_name>_set。

因爲一個字段的反轉名稱應該是惟一的,當你給你的模型設計子類時,要格外當心。爲了規避名稱衝突,名稱的一部分應該含有'%(app_label)s'和'%(model_name)s',它們會被應用標籤的名稱和模型的名稱替換,兩者都是小寫的。詳見抽象模型的關聯名稱。

get_latest_by

Options.get_latest_by
模型中某個可排序的字段的名稱,好比DateField、DateTimeField或者IntegerField。它指定了Manager的latest()和earliest()中使用的默認字段。

例如:

get_latest_by = "order_date"
詳見latest() 文檔。

managed

Options.managed
默認爲True,意思是Django在migrate命令中建立合適的數據表,而且會在 flush 管理命令中移除它們。換句話說,Django會管理這些數據表的生命週期。

若是是False,Django 就不會爲當前模型建立和刪除數據表。若是當前模型表示一個已經存在的,經過其它方法創建的數據庫視圖或者數據表,這會至關有用。這是設置爲managed=False時惟一的不一樣之處。. 模型處理的其它任何方面都和日常同樣。這包括:

若是你不聲明它的話,會向你的模型中添加一個自增主鍵。爲了不給後面的代碼讀者帶來混亂,強烈推薦你在使用未被管理的模型時,指定數據表中全部的列。

若是一個帶有managed=False的模型含有指向其餘未被管理模型的ManyToManyField,那麼多對多鏈接的中介表也不會被建立。可是,一個被管理模型和一個未被管理模型之間的中介表會被建立。

若是你須要修改這一默認行爲,建立中介表做爲顯式的模型(設置爲managed),而且使用ManyToManyField.through爲你的自定義模型建立關聯。

對於帶有managed=False的模型的測試,你要確保在測試啓動時創建正確的表。

若是你對修改模型類在Python層面的行爲感興趣,你能夠設置 managed=False ,而且爲一個已經存在的模型建立一個副本。可是這種狀況下使用代理模型纔是更好的方法。

order_with_respect_to

Options.order_with_respect_to
按照給定的字段把這個對象標記爲」可排序的「。這一屬性一般用到關聯對象上面,使它在父對象中有序。好比,若是Answer和 Question相關聯,一個問題有至少一個答案,而且答案的順序很是重要,你能夠這樣作:

from django.db import models

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

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

    class Meta:
        order_with_respect_to = 'question'


當order_with_respect_to 設置以後,模型會提供兩個用於設置和獲取關聯對象順序的方法:get_RELATED_order() 和set_RELATED_order(),其中RELATED是小寫的模型名稱。例如,假設一個 Question 對象有不少相關聯的Answer對象,返回的列表中含有與之相關聯Answer對象的主鍵:

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


與Question對象相關聯的Answer對象的順序,能夠經過傳入一格包含Answer 主鍵的列表來設置:

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

相關聯的對象也有兩個方法, get_next_in_order() 和get_previous_in_order(),用於按照合適的順序訪問它們。假設Answer對象按照 id來排序:

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

修改 order_with_respect_to

order_with_respect_to屬性會添加一個額外的字段(/數據表中的列)叫作_order,因此若是你在首次遷移以後添加或者修改了order_with_respect_to屬性,要確保執行和應用了合適的遷移操做。

ordering

Options.ordering
對象默認的順序,獲取一個對象的列表時使用:

ordering = ['-order_date']
它是一個字符串的列表或元組。每一個字符串是一個字段名,前面帶有可選的「-」前綴表示倒序。前面沒有「-」的字段表示正序。使用"?"來表示隨機排序。

例如,要按照pub_date字段的正序排序,這樣寫:

ordering = ['pub_date']
按照pub_date字段的倒序排序,這樣寫:

ordering = ['-pub_date']
先按照pub_date的倒序排序,再按照 author 的正序排序,這樣寫:

ordering = ['-pub_date', 'author']
警告

排序並非沒有任何代價的操做。你向ordering屬性添加的每一個字段都會產生你數據庫的開銷。你添加的每一個外鍵也會隱式包含它的默認順序。

permissions

Options.permissions
設置建立對象時權限表中額外的權限。增長、刪除和修改權限會自動爲每一個模型建立。這個例子指定了一種額外的權限,can_deliver_pizzas:

permissions = (("can_deliver_pizzas", "Can deliver pizzas"),)
它是一個包含二元組的元組或者列表,格式爲 (permission_code, human_readable_permission_name)。

default_permissions

Options.default_permissions
New in Django 1.7.
默認爲('add', 'change', 'delete')。你能夠自定義這個列表,好比,若是你的應用不須要默認權限中的任何一項,能夠把它設置成空列表。在模型被migrate命令建立以前,這個屬性必須被指定,以防一些遺漏的屬性被建立。

proxy

Options.proxy
若是proxy = True, 它做爲另外一個模型的子類,將會做爲一個代理模型。

select_on_save

Options.select_on_save
該選項決定了Django是否採用1.6以前的 django.db.models.Model.save()算法。舊的算法使用SELECT來判斷是否存在須要更新的行。而新式的算法直接嘗試使用 UPDATE。在一些小几率的狀況中,一個已存在的行的UPDATE操做並不對Django可見。好比PostgreSQL的ON UPDATE觸發器會返回NULL。這種狀況下,新式的算法會在最後執行 INSERT 操做,即便這一行已經在數據庫中存在。

一般這個屬性不須要設置。默認爲False。

關於舊式和新式兩種算法,請參見django.db.models.Model.save()。

unique_together

Options.unique_together
用來設置的不重複的字段組合:

unique_together = (("driver", "restaurant"),)
它是一個元組的元組,組合起來的時候必須是惟一的。它在Django後臺中被使用,在數據庫層上約束數據(好比,在  CREATE TABLE  語句中包含  UNIQUE語句)。

爲了方便起見,處理單一字段的集合時,unique_together 能夠是一維的元組:

unique_together = ("driver", "restaurant")
ManyToManyField不能包含在unique_together中。(這意味着什麼並不清楚!)若是你須要驗證ManyToManyField關聯的惟一性,試着使用信號或者顯式的貫穿模型(explicit through model)。

Changed in Django 1.7:
當unique_together的約束被違反時,模型校驗期間會拋出ValidationError異常。


index_together

Options.index_together
用來設置帶有索引的字段組合:

index_together = [
    ["pub_date", "deadline"],
]
列表中的字段將會創建索引(例如,會在CREATE INDEX語句中被使用)。

Changed in Django 1.7.
爲了方便起見,處理單一字段的集合時,index_together能夠是一個一維的列表。

index_together = ["pub_date", "deadline"]


verbose_name

Options.verbose_name
對象的一個易於理解的名稱,爲單數:

verbose_name = "pizza"
若是此項沒有設置,Django會把類名拆分開來做爲自述名,好比CamelCase 會變成camel case,

verbose_name_plural

Options.verbose_name_plural
該對象複數形式的名稱:

verbose_name_plural = "stories" 若是此項沒有設置,Django 會使用 verbose_name + "s"。

相關文章
相關標籤/搜索