Django之Models的class Meta


模型元數據是“任何不是字段的數據”,比如排序選項(ordering),數據庫表名(db_table)或者人類可讀的單復數名稱(verbose_name 和verbose_name_plural)。在模型中添加class Meta是完全可選的,所有選項都不是必須的。

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的公共屬性:

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表並沒有被創建:

$ 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相關聯,一個問題有至少一個答案,並且答案的順序非常重要,你可以這樣做:

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屬性,要確保執行和應用了合適的遷移操作。

 

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"。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM