Django之Models的class Meta 作者:@skyflask轉載本文請註明出處:https://www.cnblogs.com/skyflask/p/9544898.html 目錄 1、abstract2、app_label3、db_table4、db_tablespace5、defa ...
Django之Models的class Meta
作者:@skyflask
轉載本文請註明出處:https://www.cnblogs.com/skyflask/p/9544898.html
目錄
1、abstract
2、app_label
3、db_table
4、db_tablespace
5、default_related_name
6、get_latest_by
7、managed
8、order_with_respect_to
9、ordering
10、permissions
11、default_permissions
12、proxy
13、select_on_save
14、unique_together
15、index_together
16、verbose_name
17、verbose_name_plural
模型元數據是“任何不是欄位的數據”,比如排序選項(ordering),資料庫表名(db_table)或者人類可讀的單複數名稱(verbose_name 和verbose_name_plural)。在模型中添加class Meta是完全可選的,所有選項都不是必須的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
class Book(models.Model):
name =models.CharField(max_length=32)
def __str__(self):
return self.name
class Author(models.Model):
name = models.CharField(max_length=32)
m = models.ManyToManyField('Book')
def __str__(self):
return self.name
class A_to_B(models.Model):
bid = models.ForeignKey(Book)
aid = models.ForeignKey(Author)
class Meta:
unique_together = (
('bid','aid'),
)
|
上面定義了2張表,一張是Book表,一張是Author表,然後定義了一個多對多關係的A_to_B表,最後定義了元數據,它的意思上面的多對多表具有唯一約束。
可用的元選項
1、abstract
這個屬性是定義當前的模型類是不是一個抽象類。所謂抽象類是不會相應資料庫表的。一般我們用它來歸納一些公共屬性欄位,然後繼承它的子類能夠繼承這些欄位。
比方以下的代碼中Human是一個抽象類。Employee是一個繼承了Human的子類,那麼在執行syncdb命令時,不會生成Human表。可是會生成一個Employee表,它包括了Human中繼承來的欄位。以後假設再加入一個Customer模型類,它能夠相同繼承Human的公共屬性:
1 2 3 4 5 6 7 8 9 10 11 |
class Human(models.Model):
name=models.CharField(max_length=100)
GENDER_CHOICE=((u'M',u'Male'),(u'F',u'Female'),)
gender=models.CharField(max_length=2,choices=GENDER_CHOICE,null=True)
class Meta:
abstract=True
class Employee(Human):
joint_date=models.DateField()
class Customer(Human):
first_name=models.CharField(max_length=100)
birth_day=models.DateField()
|
上面的代碼,運行python manage.py syncdb 後的輸出結果入下。能夠看出Human表並沒有被創建:
1 2 3 4 5 6 7 |
$ python manage.py syncdb
Creating tables ...
Creating table myapp_employee
Creating table myapp_customer
Installing custom SQL ...
Installing indexes ...
No fixtures found.
|
2、app_label
Options.app_label
如果一個模型位於標準的位置之外(應用的models.py 或models 包),該模型必須定義它屬於哪個應用:
app_label = 'myapp'
New in Django 1.7:
定義在應用的models 模塊以外的模型,不再需要app_label。
3、db_table
Options.db_table
該模型所用的數據表的名稱:
db_table = 'music_album'
為節省你的時間,Django 會根據模型類的名稱和包含它的應用的名稱自動指定資料庫表名稱。一個模型的資料庫表名稱,由這個模型的“應用標簽”(在manage.py startapp中使用的名稱)和模型類名稱之間加上下劃線組成。
舉個例子, bookstore應用(使用 manage.py startapp bookstore 創建),裡面有個名為 Book的模型,那數據表的名稱就是 bookstore_book 。
使用 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 註意事項 。
4、db_tablespace
Options.db_tablespace
當前模型所使用的資料庫表空間 的名字。預設值是項目設置中的DEFAULT_TABLESPACE,如果它存在的話。如果後端並不支持表空間,這個選項可以忽略。
5、default_related_name
Options.default_related_name
New in Django 1.8.
這個名字會預設被用於一個關聯對象到當前對象的關係。預設為 <model_name>_set。
由於一個欄位的反轉名稱應該是唯一的,當你給你的模型設計子類時,要格外小心。為了規避名稱衝突,名稱的一部分應該含有'%(app_label)s'和'%(model_name)s',它們會被應用標簽的名稱和模型的名稱替換,二者都是小寫的。詳見抽象模型的關聯名稱。
6、get_latest_by
Options.get_latest_by
模型中某個可排序的欄位的名稱,比如DateField、DateTimeField或者IntegerField。它指定了Manager的latest()和earliest()中使用的預設欄位。
例如:
get_latest_by = "order_date"
詳見latest() 文檔。
7、managed
Options.managed
預設為True,意思是Django在migrate命令中創建合適的數據表,並且會在 flush 管理命令中移除它們。換句話說,Django會管理這些數據表的生命周期。
如果是False,Django 就不會為當前模型創建和刪除數據表。如果當前模型表示一個已經存在的,通過其它方法建立的資料庫視圖或者數據表,這會相當有用。這是設置為managed=False時唯一的不同之處。. 模型處理的其它任何方面都和平常一樣。這包括:
如果你不聲明它的話,會向你的模型中添加一個自增主鍵。為了避免給後面的代碼讀者帶來混亂,強烈推薦你在使用未被管理的模型時,指定數據表中所有的列。
如果一個帶有managed=False的模型含有指向其他未被管理模型的ManyToManyField,那麼多對多連接的中介表也不會被創建。但是,一個被管理模型和一個未被管理模型之間的中介表會被創建。
如果你需要修改這一預設行為,創建中介表作為顯式的模型(設置為managed),並且使用ManyToManyField.through為你的自定義模型創建關聯。
對於帶有managed=False的模型的測試,你要確保在測試啟動時建立正確的表。
如果你對修改模型類在Python層面的行為感興趣,你可以設置 managed=False ,並且為一個已經存在的模型創建一個副本。但是這種情況下使用代理模型才是更好的方法。
8、order_with_respect_to
Options.order_with_respect_to
按照給定的欄位把這個對象標記為”可排序的“。這一屬性通常用到關聯對象上面,使它在父對象中有序。比如,如果Answer和 Question相關聯,一個問題有至少一個答案,並且答案的順序非常重要,你可以這樣做:
1 2 3 4 5 6 7 8 9 10 11 12 |
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對象的主鍵:
1 2 3 |
>>> 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來排序:
1 2 3 4 5 |
>>> 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屬性,要確保執行和應用了合適的遷移操作。
9、ordering
Options.ordering
對象預設的順序,獲取一個對象的列表時使用:
ordering = ['-order_date']
它是一個字元串的列表或元組。每個字元串是一個欄位名,前面帶有可選的“-”首碼表示倒序。前面沒有“-”的欄位表示正序。使用"?"來表示隨機排序。
例如,要按照pub_date欄位的正序排序,這樣寫:
ordering = ['pub_date']
按照pub_date欄位的倒序排序,這樣寫:
ordering = ['-pub_date']
先按照pub_date的倒序排序,再按照 author 的正序排序,這樣寫:
ordering = ['-pub_date', 'author']
警告
排序並不是沒有任何代價的操作。你向ordering屬性添加的每個欄位都會產生你資料庫的開銷。你添加的每個外鍵也會隱式包含它的預設順序。
10、permissions
Options.permissions
設置創建對象時許可權表中額外的許可權。增加、刪除和修改許可權會自動為每個模型創建。這個例子指定了一種額外的許可權,can_deliver_pizzas:
permissions = (("can_deliver_pizzas", "Can deliver pizzas"),)
它是一個包含二元組的元組或者列表,格式為 (permission_code, human_readable_permission_name)。
11、default_permissions
Options.default_permissions
New in Django 1.7.
預設為('add', 'change', 'delete')。你可以自定義這個列表,比如,如果你的應用不需要預設許可權中的任何一項,可以把它設置成空列表。在模型被migrate命令創建之前,這個屬性必須被指定,以防一些遺漏的屬性被創建。
12、proxy
Options.proxy
如果proxy = True, 它作為另一個模型的子類,將會作為一個代理模型。
13、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()。
14、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異常。
15、index_together
用來設置帶有索引的欄位組合:
index_together = [
["pub_date", "deadline"],
]
列表中的欄位將會建立索引(例如,會在CREATE INDEX語句中被使用)。
Changed in Django 1.7.
為了方便起見,處理單一欄位的集合時,index_together可以是一個一維的列表。
index_together = ["pub_date", "deadline"]
16、verbose_name
Options.verbose_name
對象的一個易於理解的名稱,為單數:
verbose_name = "pizza"
如果此項沒有設置,Django會把類名拆分開來作為自述名,比如CamelCase 會變成camel case,
17、verbose_name_plural
Options.verbose_name_plural
該對象複數形式的名稱:
verbose_name_plural = "stories"
如果此項沒有設置,Django 會使用 verbose_name + "s"。