在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ Python/ 模型
編寫(xiě)自定義存儲(chǔ)系統(tǒng)
高級(jí)
編寫(xiě)你的第一個(gè)Django應(yīng)用,第5部分
視圖層
Django管理文檔生成器
編寫(xiě)你的第一個(gè) Django 程序 第3部分
編寫(xiě)你的第一個(gè)Django應(yīng)用,第6部分
模型層
中間件
測(cè)試
數(shù)據(jù)庫(kù)訪(fǎng)問(wèn)優(yōu)化
文件上傳
中間件
驗(yàn)證器
基于類(lèi)的內(nèi)建通用視圖
部署靜態(tài)文件
使用Django認(rèn)證系統(tǒng)
高級(jí)教程:如何編寫(xiě)可重用的應(yīng)用
Model 類(lèi)參考
Django 初探
使用Django輸出PDF
模型的實(shí)例
模型
文件上傳
進(jìn)行原始的sql查詢(xún)
面向程序員
中間件
編寫(xiě)數(shù)據(jù)庫(kù)遷移
TemplateResponse 和 SimpleTemplateResponse
異常
Django中的測(cè)試
基礎(chǔ)
管理器
File對(duì)象
URL調(diào)度器
加密簽名
國(guó)際化和本地化
日志
查詢(xún)集
django-admin 和 manage.py
使用基于類(lèi)的視圖處理表單
聚合
內(nèi)建基于類(lèi)的視圖的API
如何使用會(huì)話(huà)
部署 Django
其它
其它核心功能
高級(jí)
Django中的密碼管理
模型元選項(xiàng)
按需內(nèi)容處理
查找 API 參考
高級(jí)
Django 的快捷函數(shù)
Django 的設(shè)置
Admin
開(kāi)發(fā)過(guò)程
新手入門(mén)
基于類(lèi)的視圖
模型實(shí)例參考
信號(hào)
表單素材 ( <code>Media</code> 類(lèi))
自定義查找
常見(jiàn)的網(wǎng)站應(yīng)用工具
模型
django.contrib.humanize
Django模版語(yǔ)言
點(diǎn)擊劫持保護(hù)
管理操作
編寫(xiě)你的第一個(gè) Django 程序 第2部分
Django安全
模式編輯器
多數(shù)據(jù)庫(kù)
部署
基于類(lèi)的視圖
內(nèi)建的視圖
視圖裝飾器
面向設(shè)計(jì)師
編寫(xiě)視圖
應(yīng)用程序
如何使用WSGI 部署
參考
表單 API
文件儲(chǔ)存API
認(rèn)證
國(guó)際化和本地化
錯(cuò)誤報(bào)告
基礎(chǔ)
基礎(chǔ)
將遺留數(shù)據(jù)庫(kù)整合到Django
教程
Django異常
編寫(xiě)你的第一個(gè) Django 程序 第4部分
遷移
分頁(yè)
重定向應(yīng)用
表單
從零開(kāi)始
為模型提供初始數(shù)據(jù)
設(shè)置
使用Django輸出CSV
關(guān)聯(lián)對(duì)象參考
使用表單
Django 中的用戶(hù)認(rèn)證
快速安裝指南
安全問(wèn)題歸檔
數(shù)據(jù)庫(kù)函數(shù)
編寫(xiě)自定義的django-admin命令
高級(jí)教程
管理文件
格式本地化
基于類(lèi)的通用視圖 —— 索引
安全
系統(tǒng)檢查框架
為Django編寫(xiě)首個(gè)補(bǔ)丁
模板層
Widgets
編寫(xiě)你的第一個(gè) Django 程序 第1部分
執(zhí)行查詢(xún)

模型

模型是你的數(shù)據(jù)的唯一的、權(quán)威的信息源。它包含你所儲(chǔ)存數(shù)據(jù)的必要字段和行為。通常,每個(gè)模型對(duì)應(yīng)數(shù)據(jù)庫(kù)中唯一的一張表。

基礎(chǔ):

  • 每個(gè)模型都是django.db.models.Model 的一個(gè)Python 子類(lèi)。
  • 模型的每個(gè)屬性都表示數(shù)據(jù)庫(kù)中的一個(gè)字段。
  • Django 提供一套自動(dòng)生成的用于數(shù)據(jù)庫(kù)訪(fǎng)問(wèn)的API;詳見(jiàn)執(zhí)行查詢(xún)。

簡(jiǎn)短的例子

這個(gè)例子定義一個(gè)Person模型,它有first_namelast_name 兩個(gè)屬性:

from django.db import models

class Person(models.Model):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=30)

first_namelast_name是模型的兩個(gè)字段。每個(gè)字段都被指定成一個(gè)類(lèi)屬性,每個(gè)屬性映射到一個(gè)數(shù)據(jù)庫(kù)的列。

上面的Person 模型會(huì)在數(shù)據(jù)庫(kù)中創(chuàng)建這樣一張表:

CREATE TABLE myapp_person (
    "id" serial NOT NULL PRIMARY KEY,
    "first_name" varchar(30) NOT NULL,
    "last_name" varchar(30) NOT NULL
);

一些技術(shù)上的注意事項(xiàng):

  • 這個(gè)表的名稱(chēng)myapp_person,是根據(jù) 模型中的元數(shù)據(jù)自動(dòng)生成的,也可以覆寫(xiě)為別的名稱(chēng),詳見(jiàn)Table names
  • id 字段是自動(dòng)添加的,但這個(gè)行為可以被重寫(xiě)。詳見(jiàn)自增主鍵字段。
  • 這個(gè)例子中的CREATE TABLE SQL 語(yǔ)句使用PostgreSQL 語(yǔ)法格式,要注意的是Django 會(huì)根據(jù)設(shè)置文件 中指定的數(shù)據(jù)庫(kù)類(lèi)型來(lái)使用相應(yīng)的SQL 語(yǔ)句。

使用模型

定義好模型之后,你需要告訴Django _使用_這些模型。你要做的就是修改配置文件中的INSTALLED_APPS 設(shè)置,在其中添加models.py所在應(yīng)用的名稱(chēng)。

例如,如果你的應(yīng)用的模型位于myapp.models模塊(manage.py startapp 腳本為一個(gè)應(yīng)用創(chuàng)建的包結(jié)構(gòu)),INSTALLED_APPS部分看上去應(yīng)該是:

INSTALLED_APPS = (
    #...
    'myapp',
    #...
)

當(dāng)你在INSTALLED_APPS 中添加新的應(yīng)用名時(shí),請(qǐng)確保運(yùn)行命令manage.py migrate,可以首先使用manage.py makemigrations 來(lái)為它們生成遷移腳本。

字段

模型中不可或缺且最為重要的,就是字段集,它是一組數(shù)據(jù)庫(kù)字段的列表。字段被指定為類(lèi)屬性。 要注意選擇的字段名稱(chēng)不要和模型 API 沖突,比如cleansave 或者delete

例如:

from django.db import models

class Musician(models.Model):
    first_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)
    instrument = models.CharField(max_length=100)

class Album(models.Model):
    artist = models.ForeignKey(Musician)
    name = models.CharField(max_length=100)
    release_date = models.DateField()
    num_stars = models.IntegerField()

字段類(lèi)型

模型中的每個(gè)字段都是 Field 子類(lèi)的某個(gè)實(shí)例。Django 根據(jù)字段類(lèi)的類(lèi)型確定以下信息:

  • 數(shù)據(jù)庫(kù)當(dāng)中的列類(lèi)型 (比如, INTEGER, VARCHAR)。
  • 渲染表單時(shí)使用的默認(rèn)HTML 部件(例如,<input type="text">, <select>)。
  • 最低限度的驗(yàn)證需求,它被用在 Django 管理站點(diǎn)和自動(dòng)生成的表單中。

Django 自帶數(shù)十種內(nèi)置的字段類(lèi)型;完整字段類(lèi)型列表可以在模型字段參考 中找到。如果內(nèi)置類(lèi)型仍不能滿(mǎn)足你的要求,你可以自由地編寫(xiě)符合你要求的字段類(lèi)型; 詳見(jiàn)編寫(xiě)自定義的模型字段。

字段選項(xiàng)

每個(gè)字段有一些特有的參數(shù),詳見(jiàn)模型字段參考。例如,CharField(和它的派生類(lèi))需要max_length 參數(shù)來(lái)指定VARCHAR 數(shù)據(jù)庫(kù)字段的大小。

還有一些適用于所有字段的通用參數(shù)。 這些參數(shù)在參考中有詳細(xì)定義,這里我們只簡(jiǎn)單介紹一些最常用的:

null

如果為True,Django 將用NULL 來(lái)在數(shù)據(jù)庫(kù)中存儲(chǔ)空值。 默認(rèn)值是 False.

blank

如果為True,該字段允許不填。默認(rèn)為False

要注意,這與 null 不同。null純粹是數(shù)據(jù)庫(kù)范疇的,而 blank 是數(shù)據(jù)驗(yàn)證范疇的。如果一個(gè)字段的blank=True,表單的驗(yàn)證將允許該字段是空值。如果字段的blank=False,該字段就是必填的。

choices

由二元組組成的一個(gè)可迭代對(duì)象(例如,列表或元組),用來(lái)給字段提供選擇項(xiàng)。 如果設(shè)置了choices ,默認(rèn)的表單將是一個(gè)選擇框而不是標(biāo)準(zhǔn)的文本框,而且這個(gè)選擇框的選項(xiàng)就是choices 中的選項(xiàng)。

這是一個(gè)關(guān)于 choices 列表的例子:

YEAR_IN_SCHOOL_CHOICES = (
    ('FR', 'Freshman'),
    ('SO', 'Sophomore'),
    ('JR', 'Junior'),
    ('SR', 'Senior'),
    ('GR', 'Graduate'),
)

每個(gè)元組中的第一個(gè)元素,是存儲(chǔ)在數(shù)據(jù)庫(kù)中的值;第二個(gè)元素是在管理界面或 ModelChoiceField 中用作顯示的內(nèi)容。 在一個(gè)給定的 model 類(lèi)的實(shí)例中,想得到某個(gè) choices 字段的顯示值,就調(diào)用 get_FOO_display 方法(這里的 FOO 就是 choices 字段的名稱(chēng) )。例如:

from django.db import models

class Person(models.Model):
    SHIRT_SIZES = (
        ('S', 'Small'),
        ('M', 'Medium'),
        ('L', 'Large'),
    )
    name = models.CharField(max_length=60)
    shirt_size = models.CharField(max_length=1, choices=SHIRT_SIZES)
>>> p = Person(name="Fred Flintstone", shirt_size="L")
>>> p.save()
>>> p.shirt_size
'L'
>>> p.get_shirt_size_display()
'Large'

default

字段的默認(rèn)值??梢允且粋€(gè)值或者可調(diào)用對(duì)象。如果可調(diào)用 ,每有新對(duì)象被創(chuàng)建它都會(huì)被調(diào)用。

help_text

表單部件額外顯示的幫助內(nèi)容。即使字段不在表單中使用,它對(duì)生成文檔也很有用。

primary_key

如果為True,那么這個(gè)字段就是模型的主鍵。

如果你沒(méi)有指定任何一個(gè)字段的primary_key=True,Django 就會(huì)自動(dòng)添加一個(gè)IntegerField 字段做為主鍵,所以除非你想覆蓋默認(rèn)的主鍵行為,否則沒(méi)必要設(shè)置任何一個(gè)字段的primary_key=True。詳見(jiàn)自增主鍵字段。

主鍵字段是只讀的。如果你在一個(gè)已存在的對(duì)象上面更改主鍵的值并且保存,一個(gè)新的對(duì)象將會(huì)在原有對(duì)象之外創(chuàng)建出來(lái)。例如:

from django.db import models

class Fruit(models.Model):
    name = models.CharField(max_length=100, primary_key=True)
>>> fruit = Fruit.objects.create(name='Apple')
>>> fruit.name = 'Pear'
>>> fruit.save()
>>> Fruit.objects.values_list('name', flat=True)
['Apple', 'Pear']

unique

如果該值設(shè)置為 True, 這個(gè)數(shù)據(jù)字段的值在整張表中必須是唯一的

再說(shuō)一次,這些僅僅是常用字段的簡(jiǎn)短介紹, 要了解詳細(xì)內(nèi)容,請(qǐng)查看 通用 model 字段選項(xiàng)參考(common model field option reference).

自增主鍵字段

默認(rèn)情況下,Django 會(huì)給每個(gè)模型添加下面這個(gè)字段:

id = models.AutoField(primary_key=True)

這是一個(gè)自增主鍵字段。

如果你想指定一個(gè)自定義主鍵字段,只要在某個(gè)字段上指定 primary_key=True 即可。如果 Django 看到你顯式地設(shè)置了 Field.primary_key,就不會(huì)自動(dòng)添加 id 列。

每個(gè)模型只能有一個(gè)字段指定primary_key=True(無(wú)論是顯式聲明還是自動(dòng)添加)。

字段的自述名

ForeignKey、ManyToManyFieldOneToOneField 之外,每個(gè)字段類(lèi)型都接受一個(gè)可選的位置參數(shù) —— 字段的自述名。如果沒(méi)有給定自述名,Django 將根據(jù)字段的屬性名稱(chēng)自動(dòng)創(chuàng)建自述名 —— 將屬性名稱(chēng)的下劃線(xiàn)替換成空格。

在這個(gè)例子中,自述名是 "person's first name":

first_name = models.CharField("person's first name", max_length=30)

在這個(gè)例子中,自述名是  "first name"

first_name = models.CharField(max_length=30)

ForeignKey、ManyToManyFieldOneToOneField 都要求第一個(gè)參數(shù)是一個(gè)模型類(lèi),所以要使用 verbose_name 關(guān)鍵字參數(shù)才能指定自述名:

poll = models.ForeignKey(Poll, verbose_name="the related poll")
sites = models.ManyToManyField(Site, verbose_name="list of sites")
place = models.OneToOneField(Place, verbose_name="related place")

習(xí)慣上,verbose_name 的首字母不用大寫(xiě)。Django 在必要的時(shí)候會(huì)自動(dòng)大寫(xiě)首字母。

關(guān)系

顯然,關(guān)系數(shù)據(jù)庫(kù)的威力體現(xiàn)在表之間的相互關(guān)聯(lián)。 Django 提供了三種最常見(jiàn)的數(shù)據(jù)庫(kù)關(guān)系:多對(duì)一(many-to-one),多對(duì)多(many-to-many),一對(duì)一(one-to-one)。

多對(duì)一關(guān)系 

Django 使用 django.db.models.ForeignKey 定義多對(duì)一關(guān)系。和使用其它字段類(lèi)型一樣:在模型當(dāng)中把它做為一個(gè)類(lèi)屬性包含進(jìn)來(lái)。

ForeignKey 需要一個(gè)位置參數(shù):與該模型關(guān)聯(lián)的類(lèi)。

比如,一輛Car有一個(gè)Manufacturer —— 但是一個(gè)Manufacturer 生產(chǎn)很多Car,每一輛Car 只能有一個(gè)Manufacturer —— 使用下面的定義:

from django.db import models

class Manufacturer(models.Model):
    # ...
    pass

class Car(models.Model):
    manufacturer = models.ForeignKey(Manufacturer)
    # ...

你還可以創(chuàng)建遞歸的關(guān)聯(lián)關(guān)系(對(duì)象和自己進(jìn)行多對(duì)一關(guān)聯(lián))和 與尚未定義的模型的關(guān)聯(lián)關(guān)系;詳見(jiàn)模型字段參考。

建議你用被關(guān)聯(lián)的模型的小寫(xiě)名稱(chēng)做為ForeignKey 字段的名字(例如,上面manufacturer)。當(dāng)然,你也可以起別的名字。例如:

class Car(models.Model):
    company_that_makes_it = models.ForeignKey(Manufacturer)
    # ...

另見(jiàn)

ForeignKey 字段還接受許多別的參數(shù),在模型字段參考有詳細(xì)介紹。這些選項(xiàng)幫助定義關(guān)聯(lián)關(guān)系應(yīng)該如何工作;它們都是可選的參數(shù)。

訪(fǎng)問(wèn)反向關(guān)聯(lián)對(duì)象的細(xì)節(jié),請(qǐng)見(jiàn)Following relationships backward example。

示例代碼,請(qǐng)見(jiàn)多對(duì)一關(guān)系模型示例)。

多對(duì)多關(guān)系

ManyToManyField 用來(lái)定義多對(duì)多關(guān)系,用法和其他Field 字段類(lèi)型一樣:在模型中做為一個(gè)類(lèi)屬性包含進(jìn)來(lái)。

ManyToManyField 需要一個(gè)位置參數(shù):和該模型關(guān)聯(lián)的類(lèi)。

例如,一個(gè)Pizza可以有多種Topping —— 一種Topping 可以位于多個(gè)Pizza 上,而且每個(gè)Pizza 可以有多種Topping —— 如下:

from django.db import models

class Topping(models.Model):
    # ...
    pass

class Pizza(models.Model):
    # ...
    toppings = models.ManyToManyField(Topping)

和使用ForeignKey 一樣,你也可以創(chuàng)建遞歸的關(guān)聯(lián)關(guān)系(對(duì)象與自己的多對(duì)多關(guān)聯(lián))和與尚未定義關(guān)系的模型的關(guān)聯(lián)關(guān)系;詳見(jiàn)模型字段參考。

建議你以被關(guān)聯(lián)模型名稱(chēng)的復(fù)數(shù)形式做為ManyToManyField 的名字(例如上例中的toppings)。

在哪個(gè)模型中設(shè)置 ManyToManyField 并不重要,在兩個(gè)模型中任選一個(gè)即可 —— 不要兩個(gè)模型都設(shè)置。

通常,ManyToManyField 實(shí)例應(yīng)該位于可以編輯的表單中。在上面的例子中,toppings 位于Pizza 中(而不是在 Topping 里面設(shè)置pizzasManyToManyField 字段),因?yàn)樵O(shè)想一個(gè)Pizza 有多種Topping 比一個(gè)Topping 位于多個(gè)Pizza 上要更加自然。按照上面的方式,在Pizza 的表單中將允許用戶(hù)選擇不同的Toppings。

另見(jiàn)

完整的示例參見(jiàn)多對(duì)多關(guān)系模型示例。

ManyToManyField 字段還接受別的參數(shù),在模型字段參考中有詳細(xì)介紹。這些選項(xiàng)幫助定義關(guān)系應(yīng)該如何工作;它們都是可選的。

多對(duì)多關(guān)系中的其他字段

處理類(lèi)似搭配 pizza 和 topping 這樣簡(jiǎn)單的多對(duì)多關(guān)系時(shí),使用標(biāo)準(zhǔn)的ManyToManyField  就可以了。但是,有時(shí)你可能需要關(guān)聯(lián)數(shù)據(jù)到兩個(gè)模型之間的關(guān)系上。

例如,有這樣一個(gè)應(yīng)用,它記錄音樂(lè)家所屬的音樂(lè)小組。我們可以用一個(gè)ManyToManyField 表示小組和成員之間的多對(duì)多關(guān)系。但是,有時(shí)你可能想知道更多成員關(guān)系的細(xì)節(jié),比如成員是何時(shí)加入小組的。

對(duì)于這些情況,Django 允許你指定一個(gè)模型來(lái)定義多對(duì)多關(guān)系。 你可以將其他字段放在中介模型里面。源模型的ManyToManyField 字段將使用through 參數(shù)指向中介模型。對(duì)于上面的音樂(lè)小組的例子,代碼如下:

from django.db import models

class Person(models.Model):
    name = models.CharField(max_length=128)

    def __str__(self):              # __unicode__ on Python 2
        return self.name

class Group(models.Model):
    name = models.CharField(max_length=128)
    members = models.ManyToManyField(Person, through='Membership')

    def __str__(self):              # __unicode__ on Python 2
        return self.name

class Membership(models.Model):
    person = models.ForeignKey(Person)
    group = models.ForeignKey(Group)
    date_joined = models.DateField()
    invite_reason = models.CharField(max_length=64)

在設(shè)置中介模型時(shí),要顯式指定外鍵并關(guān)聯(lián)到多對(duì)多關(guān)系涉及的模型。這個(gè)顯式聲明定義兩個(gè)模型之間是如何關(guān)聯(lián)的。

中介模型有一些限制:

  • 中介模型必須_有且只有一個(gè)_外鍵到源模型(上面例子中的Group),或者你必須使用ManyToManyField.through_fields 顯式指定Django 應(yīng)該使用的外鍵。如果你的模型中存在超個(gè)一個(gè)的外鍵,并且through_fields沒(méi)有指定,將會(huì)觸發(fā)一個(gè)無(wú)效的錯(cuò)誤。 對(duì)目標(biāo)模型的外鍵有相同的限制(上面例子中的 Person)。
  • 對(duì)于通過(guò)中介模型與自己進(jìn)行多對(duì)多關(guān)聯(lián)的模型,允許存在到同一個(gè)模型的兩個(gè)外鍵,但它們將被作為多對(duì)多關(guān)聯(lián)關(guān)系的兩個(gè)(不同的)方面。如果有超過(guò) 兩個(gè)外鍵,同樣你必須像上面一樣指定through_fields,否則將引發(fā)一個(gè)驗(yàn)證錯(cuò)誤。
  • 使用中介模型定義與自身的多對(duì)多關(guān)系時(shí),你_必須_設(shè)置 symmetrical=False(詳見(jiàn)模型字段參考)。

Changed in Django 1.7:

在Django 1.6 及之前的版本中,中介模型禁止包含多于一個(gè)的外鍵。

既然你已經(jīng)設(shè)置好ManyToManyField 來(lái)使用中介模型(在這個(gè)例子中就是Membership),接下來(lái)你要開(kāi)始創(chuàng)建多對(duì)多關(guān)系。你要做的就是創(chuàng)建中介模型的實(shí)例:

>>> ringo = Person.objects.create(name="Ringo Starr")
>>> paul = Person.objects.create(name="Paul McCartney")
>>> beatles = Group.objects.create(name="The Beatles")
>>> m1 = Membership(person=ringo, group=beatles,
...     date_joined=date(1962, 8, 16),
...     invite_reason="Needed a new drummer.")
>>> m1.save()
>>> beatles.members.all()
[<Person: Ringo Starr>]
>>> ringo.group_set.all()
[<Group: The Beatles>]
>>> m2 = Membership.objects.create(person=paul, group=beatles,
...     date_joined=date(1960, 8, 1),
...     invite_reason="Wanted to form a band.")
>>> beatles.members.all()
[<Person: Ringo Starr>, <Person: Paul McCartney>]

與普通的多對(duì)多字段不同,你_不能_使用add、 create和賦值語(yǔ)句(比如,beatles.members = [...])來(lái)創(chuàng)建關(guān)系:

# THIS WILL NOT WORK
>>> beatles.members.add(john)
# NEITHER WILL THIS
>>> beatles.members.create(name="George Harrison")
# AND NEITHER WILL THIS
>>> beatles.members = [john, paul, ringo, george]

為什么不能這樣做? 這是因?yàn)槟悴荒苤粍?chuàng)建 PersonGroup之間的關(guān)聯(lián)關(guān)系,你還要指定 Membership模型中所需要的所有信息;而簡(jiǎn)單的add、create 和賦值語(yǔ)句是做不到這一點(diǎn)的。所以它們不能在使用中介模型的多對(duì)多關(guān)系中使用。此時(shí),唯一的辦法就是創(chuàng)建中介模型的實(shí)例。

remove()方法被禁用也是出于同樣的原因。但是clear() 方法卻是可用的。它可以清空某個(gè)實(shí)例所有的多對(duì)多關(guān)系:

>>> # Beatles have broken up
>>> beatles.members.clear()
>>> # Note that this deletes the intermediate model instances
>>> Membership.objects.all()
[]

通過(guò)創(chuàng)建中介模型的實(shí)例來(lái)建立對(duì)多對(duì)多關(guān)系后,你就可以執(zhí)行查詢(xún)了。 和普通的多對(duì)多字段一樣,你可以直接使用被關(guān)聯(lián)模型的屬性進(jìn)行查詢(xún):

# Find all the groups with a member whose name starts with 'Paul'
>>> Group.objects.filter(members__name__startswith='Paul')
[<Group: The Beatles>]

如果你使用了中介模型,你也可以利用中介模型的屬性進(jìn)行查詢(xún):

# Find all the members of the Beatles that joined after 1 Jan 1961
>>> Person.objects.filter(
...     group__name='The Beatles',
...     membership__date_joined__gt=date(1961,1,1))
[<Person: Ringo Starr]

如果你需要訪(fǎng)問(wèn)一個(gè)成員的信息,你可以直接獲取Membership模型:

>>> ringos_membership = Membership.objects.get(group=beatles, person=ringo)
>>> ringos_membership.date_joined
datetime.date(1962, 8, 16)
>>> ringos_membership.invite_reason
'Needed a new drummer.'

另一種獲取相同信息的方法是,在Person對(duì)象上查詢(xún)多對(duì)多反轉(zhuǎn)關(guān)系

>>> ringos_membership = ringo.membership_set.get(group=beatles)
>>> ringos_membership.date_joined
datetime.date(1962, 8, 16)
>>> ringos_membership.invite_reason
'Needed a new drummer.'

一對(duì)一關(guān)系

OneToOneField用來(lái)定義一對(duì)一關(guān)系。 用法和其他字段類(lèi)型一樣:在模型里面做為類(lèi)屬性包含進(jìn)來(lái)。

當(dāng)某個(gè)對(duì)象想擴(kuò)展自另一個(gè)對(duì)象時(shí),最常用的方式就是在這個(gè)對(duì)象的主鍵上添加一對(duì)一關(guān)系。

OneToOneField要一個(gè)位置參數(shù):與模型關(guān)聯(lián)的類(lèi)。

例如,你想建一個(gè)“places” 數(shù)據(jù)庫(kù),里面有一些常用的字段,比如address、 phone number 等等。 接下來(lái),如果你想在Place 數(shù)據(jù)庫(kù)的基礎(chǔ)上建立一個(gè)Restaurant 數(shù)據(jù)庫(kù),而不想將已有的字段復(fù)制到Restaurant模型,那你可以在 Restaurant 添加一個(gè)OneToOneField 字段,這個(gè)字段指向Place(因?yàn)镽estaurant 本身就是一個(gè)Place;事實(shí)上,在處理這個(gè)問(wèn)題的時(shí)候,你應(yīng)該使用一個(gè)典型的 繼承,它隱含一個(gè)一對(duì)一關(guān)系)。

和使用 ForeignKey一樣,你可以定義 遞歸的關(guān)聯(lián)關(guān)系引用尚未定義關(guān)系的模型。詳見(jiàn)模型字段參考。

另見(jiàn)

一對(duì)一關(guān)系的模型例子 中有一套完整的例子。

OneToOneField字段也接受一個(gè)特定的可選的parent_link參數(shù),在模型字段參考 中有詳細(xì)介紹。

在以前的版本中,OneToOneField 字段會(huì)自動(dòng)變成模型 的主鍵。不過(guò)現(xiàn)在已經(jīng)不這么做了(不過(guò)要是你愿意的話(huà),你仍可以傳遞 primary_key參數(shù)來(lái)創(chuàng)建主鍵字段)。所以一個(gè) 模型 中可以有多個(gè)OneToOneField 字段。

跨文件的模型

訪(fǎng)問(wèn)其他應(yīng)用的模型是非常容易的。 在文件頂部你定義模型的地方,導(dǎo)入相關(guān)的模型來(lái)實(shí)現(xiàn)它。然后,無(wú)論在哪里需要的話(huà),都可以引用它。例如:

from django.db import models
from geography.models import ZipCode

class Restaurant(models.Model):
    # ...
    zip_code = models.ForeignKey(ZipCode)

字段命名的限制

Django 對(duì)字段的命名只有兩個(gè)限制:

  1. 字段的名稱(chēng)不能是Python 保留的關(guān)鍵字,因?yàn)檫@將導(dǎo)致一個(gè)Python 語(yǔ)法錯(cuò)誤。例如:

      class Example(models.Model):
          pass = models.IntegerField() # 'pass' is a reserved word!
    
  2. 由于Django 查詢(xún)語(yǔ)法的工作方式,字段名稱(chēng)中連續(xù)的下劃線(xiàn)不能超過(guò)一個(gè)。例如:

      class Example(models.Model):
          foo__bar = models.IntegerField() # 'foo__bar' has two underscores!
    

這些限制有變通的方法,因?yàn)闆](méi)有要求字段名稱(chēng)必須與數(shù)據(jù)庫(kù)的列名匹配。參 db_column 選項(xiàng)。

SQL 的保留字例如joinwhereselect,可以用作模型的字段名,因?yàn)镈jango 會(huì)對(duì)底層的SQL 查詢(xún)語(yǔ)句中的數(shù)據(jù)庫(kù)表名和列名進(jìn)行轉(zhuǎn)義。 它根據(jù)你的數(shù)據(jù)庫(kù)引擎使用不同的引用語(yǔ)法。

自定義字段類(lèi)型

如果已有的模型字段都不合適,或者你想用到一些很少見(jiàn)的數(shù)據(jù)庫(kù)列類(lèi)型的優(yōu)點(diǎn),你可以創(chuàng)建你自己的字段類(lèi)型。創(chuàng)建你自己的字段在編寫(xiě)自定義的模型字段中有完整講述。

元選項(xiàng)

使用內(nèi)部的class Meta 定義模型的元數(shù)據(jù),例如:

from django.db import models

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

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

模型元數(shù)據(jù)是“任何不是字段的數(shù)據(jù)”,比如排序選項(xiàng)(ordering),數(shù)據(jù)表名(db_table)或者人類(lèi)可讀的單復(fù)數(shù)名稱(chēng)(verbose_nameverbose_name_plural)。在模型中添加class Meta是完全可選的,所有選項(xiàng)都不是必須的。

所有選項(xiàng)的完整列表可以在模型選項(xiàng)參考找到。

模型的屬性

objects

The most important attribute of a model is the Manager. It’s the interface through which database query operations are provided to Django models and is used to retrieve the instances from the database. If no custom Manager is defined, the default name is objects. Managers are only accessible via model classes, not the model instances.

模型的方法

可以在模型上定義自定義的方法來(lái)給你的對(duì)象添加自定義的“底層”功能。Manager 方法用于“表范圍”的事務(wù),模型的方法應(yīng)該著眼于特定的模型實(shí)例。

這是一個(gè)非常有價(jià)值的技術(shù),讓業(yè)務(wù)邏輯位于同一個(gè)地方 —— 模型中。

例如,下面的模型具有一些自定義的方法:

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):
        "Returns the person's full name."
        return '%s %s' % (self.first_name, self.last_name)
    full_name = property(_get_full_name)

這個(gè)例子中的最后一個(gè)方法是一個(gè)property

模型實(shí)例參考 具有一個(gè)完整的為模型自動(dòng)生成的方法 列表。你可以覆蓋它們 —— 參見(jiàn)下文覆蓋模型預(yù)定義的方法 —— 但是有些方法你會(huì)始終想要重新定義:

__str__() (Python 3)

Python 3 equivalent of __unicode__().

__unicode__() (Python 2)

一個(gè)Python “魔法方法”,返回對(duì)象的Unicode “表示形式”。當(dāng)模型實(shí)例需要強(qiáng)制轉(zhuǎn)換并顯示為普通的字符串時(shí),Python 和Django 將使用這個(gè)方法。最明顯是在交互式控制臺(tái)或者管理站點(diǎn)顯示一個(gè)對(duì)象的時(shí)候。

將將永遠(yuǎn)想要定義這個(gè)方法;默認(rèn)的方法幾乎沒(méi)有意義。

get_absolute_url()

它告訴Django 如何計(jì)算一個(gè)對(duì)象的URL。Django 在它的管理站點(diǎn)中使用到這個(gè)方法,在其它任何需要計(jì)算一個(gè)對(duì)象的URL 時(shí)也將用到。

任何具有唯一標(biāo)識(shí)自己的URL 的對(duì)象都應(yīng)該定義這個(gè)方法。

覆蓋預(yù)定義的模型方法

還有另外一部分封裝數(shù)據(jù)庫(kù)行為的模型方法,你可能想要自定義它們。特別是,你將要經(jīng)常改變save()delete() 的工作方式。

你可以自由覆蓋這些方法(和其它任何模型方法)來(lái)改變它們的行為。

覆蓋內(nèi)建模型方法的一個(gè)典型的使用場(chǎng)景是,你想在保存一個(gè)對(duì)象時(shí)做一些其它事情。例如(參見(jiàn)save() 中關(guān)于它接受的參數(shù)的文檔):

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.

必須要記住調(diào)用超類(lèi)的方法—— super(Blog, self).save(*args, **kwargs) —— 來(lái)確保對(duì)象被保存到數(shù)據(jù)庫(kù)中。如果你忘記調(diào)用超類(lèi)的這個(gè)方法,默認(rèn)的行為將不會(huì)發(fā)生且數(shù)據(jù)庫(kù)不會(huì)有任何改變。

還要記住傳遞參數(shù)給這個(gè)模型方法 —— 即*args, **kwargs。 Django 未來(lái)將一直會(huì)擴(kuò)展內(nèi)建模型方法的功能并添加新的參數(shù)。如果在你的方法定義中使用*args, **kwargs,將保證你的代碼自動(dòng)支持這些新的參數(shù)。

Overridden model methods are not called on bulk operations

注意,當(dāng)使用查詢(xún)集批量刪除對(duì)象時(shí),將不會(huì)為每個(gè)對(duì)象調(diào)用delete() 方法。為確保自定義的刪除邏輯得到執(zhí)行,你可以使用pre_delete 和/或post_delete 信號(hào)。

不幸的是,當(dāng)批量creatingupdating 對(duì)象時(shí)沒(méi)有變通方法,因?yàn)椴粫?huì)調(diào)用save()、pre_savepost_save。

執(zhí)行自定義的SQL

另外一個(gè)常見(jiàn)的需求是在模型方法和模塊級(jí)別的方法中編寫(xiě)自定義的SQL 語(yǔ)句。關(guān)于使用原始SQL 語(yǔ)句的更多細(xì)節(jié),參見(jiàn)使用原始 SQL 的文檔。

模型繼承

Django 中的模型繼承與 Python 中普通類(lèi)繼承方式幾乎完全相同,但是本頁(yè)頭部列出的模型基本的要求還是要遵守。這表示自定義的模型類(lèi)應(yīng)該繼承django.db.models.Model。

你唯一需要作出的決定就是你是想讓父模型具有它們自己的數(shù)據(jù)庫(kù)表,還是讓父模型只持有一些共同的信息而這些信息只有在子模型中才能看到。

在Django 中有3中風(fēng)格的繼承。

  1. 通常,你只想使用父類(lèi)來(lái)持有一些信息,你不想在每個(gè)子模型中都敲一遍。這個(gè)類(lèi)永遠(yuǎn)不會(huì)單獨(dú)使用,所以你使用抽象基類(lèi)。
  2. 如果你繼承一個(gè)已經(jīng)存在的模型且想讓每個(gè)模型具有它自己的數(shù)據(jù)庫(kù)表,那么應(yīng)該使用多表繼承。
  3. 最后,如果你只是想改變模塊Python 級(jí)別的行為,而不用修改模型的字段,你可以使用代理模型。

抽象基

上一篇:視圖裝飾器下一篇:模型層