模型是有關(guān)數(shù)據(jù)的唯一確定的信息源。它包含要存儲(chǔ)數(shù)據(jù)的基本字段和行為。通常,每個(gè)模型都映射到單個(gè)數(shù)據(jù)庫(kù)表。
此示例模型定義了一個(gè)Person
,其中包含first_name
和 last_name
:
from django.db import models
class Person(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
first_name并且last_name是場(chǎng)模型。每個(gè)字段都指定為類(lèi)屬性,并且每個(gè)屬性都映射到數(shù)據(jù)庫(kù)列。
上面的Person模型將創(chuàng)建一個(gè)數(shù)據(jù)庫(kù)表,如下所示:
CREATE TABLE myapp_person (
"id" serial NOT NULL PRIMARY KEY,
"first_name" varchar(30) NOT NULL,
"last_name" varchar(30) NOT NULL
);
詳情參考官網(wǎng): https://docs.djangoproject.com/en/3.0/topics/db/models/
Django根據(jù)屬性的類(lèi)型確定以下信息:
django會(huì)為表創(chuàng)建自動(dòng)增長(zhǎng)的主鍵列,每個(gè)模型只能有一個(gè)主鍵列,如果使用選項(xiàng)設(shè)置某屬性為主鍵列后django不會(huì)再創(chuàng)建自動(dòng)增長(zhǎng)的主鍵列。
默認(rèn)創(chuàng)建的主鍵列屬性為id,可以使用pk代替,pk全拼為primary key。
pk是主鍵的別名,若主鍵名為id2,那么pk是id2的別名。
屬性命名限制:
具體語(yǔ)法如下:
屬性=models.字段類(lèi)型(選項(xiàng))
字段類(lèi) | 默認(rèn)小組件 | 說(shuō)明 |
AutoField | N/A | 根據(jù) ID 自動(dòng)遞增的 IntegerField |
BigIntegerField | NumberInput | 64 位整數(shù),與 IntegerField 很像,但取值范圍是 -9223372036854775808 到 9223372036854775807 。 |
BinaryField | N/A | 存儲(chǔ)原始二進(jìn)制數(shù)據(jù)的字段。只支持 bytes 類(lèi)型。注意,這個(gè)字段的功能有限。 |
BooleanField | CheckboxInput | 真假值字段。如果想接受 null 值,使用 NullBooleanField 。 |
CharField | TextInput | 字符串字段,針對(duì)長(zhǎng)度較小的字符串。大量文本應(yīng)該使用 TextField 。有個(gè)額外的必須參數(shù):max_length ,即字段的最大長(zhǎng)度(字符個(gè)數(shù))。 |
DateField | DateInput | 日期,在 Python 中使用 datetime.date 實(shí)例表示。有兩個(gè)額外的可選參數(shù): auto_now ,每次保存對(duì)象時(shí)自動(dòng)設(shè)為當(dāng)前日期 auto_now_add ,創(chuàng)建對(duì)象時(shí)自動(dòng)設(shè)為當(dāng)前日期。 |
DateTimeField | DateTimeInput | 日期和時(shí)間,在 Python 中使用 datetime.datetime 實(shí)例表示。與 DateField 具有相同的額外參數(shù)。 |
DecimalField | TextInput | 固定精度的小數(shù),在 Python 中使用 Decimal 實(shí)例表示。有兩個(gè)必須的參數(shù): max_digits 和 decimal_places 。 |
DurationField | TextInput | 存儲(chǔ)時(shí)間跨度,在 Python 中使用 timedelta 表示。 |
EmailField | TextInput | 一種 CharField ,使用 EmailValidator 驗(yàn)證輸入。max_length 的默認(rèn)值為 254 。 |
FileField | ClearableFileInput | 文件上傳字段。詳情見(jiàn)下面。 |
FilePathField | Select | 一種 CharField ,限定只能在文件系統(tǒng)中的特定目錄里選擇文件。 |
FloatField | NumberInput | 浮點(diǎn)數(shù),在 Python 中使用 float 實(shí)例表示。注意, field.localize 的值為 False 時(shí),默認(rèn)的小組件是 TextInput 。 |
ImageField | ClearableFileInput | 所有屬性和方法都繼承自 FileField ,此外驗(yàn)證上傳的對(duì)象是不是有效的圖像。增加了 height 和 width 兩個(gè)屬性。需要 Pillow 庫(kù)支持。 |
Django提供了定義了幾種最常見(jiàn)的數(shù)據(jù)庫(kù)關(guān)聯(lián)關(guān)系的方法:多對(duì)一,多對(duì)多,一對(duì)一。
多對(duì)一關(guān)系,需要兩個(gè)位置參數(shù),一個(gè)是關(guān)聯(lián)的模型,另一個(gè)是 on_delete
選項(xiàng),外鍵要定義在多的一方,如一個(gè)汽車(chē)廠生產(chǎn)多種汽車(chē),一輛汽車(chē)只有一個(gè)生產(chǎn)廠家
from django.db import models
class Manufacturer(models.Model):
# ...
pass
class Car(models.Model):
manufacturer = models.ForeignKey(Manufacturer, on_delete=models.CASCADE)
例如:這樣一個(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, on_delete=models.CASCADE) group = models.ForeignKey(Group, on_delete=models.CASCADE) date_joined = models.DateField() invite_reason = models.CharField(max_length=64)
您需要在設(shè)置中間模型的時(shí)候,顯式地為多對(duì)多關(guān)系中涉及的中間模型指定外鍵。這種顯式聲明定義了這兩個(gè)模型之間是如何關(guān)聯(lián)的。
在中間模型當(dāng)中有一些限制條件:
現(xiàn)在你已經(jīng)通過(guò)中間模型完成你的ManyToManyField(示例中的Membership),可以開(kāi)始創(chuàng)建一些多對(duì)多關(guān)系了。你通過(guò)實(shí)例化中間模型來(lái)創(chuàng)建關(guān)系:
>>> 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()
<QuerySet [<Person: Ringo Starr>]>
>>> ringo.group_set.all()
<QuerySet [<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()
<QuerySet [<Person: Ringo Starr>, <Person: Paul McCartney>]>
add()
、、create()
或set()
創(chuàng)建關(guān)系,只要你為任何必需的細(xì)分指定 through_defaults
:>>> beatles.members.add(john, through_defaults={'date_joined': date(1960, 8, 1)}) >>> beatles.members.create(name="George Harrison", through_defaults={'date_joined': date(1960, 8, 1)}) >>> beatles.members.set([john, paul, ringo, george], through_defaults={'date_joined': date(1960, 8, 1)})
你可能更潛在直接創(chuàng)造中間模型。
如果自定義中間模型沒(méi)有強(qiáng)制對(duì)的唯一性,調(diào)用方法會(huì)刪除所有中間模型的實(shí)例:(model1, model2)remove()
>>> Membership.objects.create(person=ringo, group=beatles, ... date_joined=date(1968, 9, 4), ... invite_reason="You've been gone for a month and we miss you.") >>> beatles.members.all() <QuerySet [<Person: Ringo Starr>, <Person: Paul McCartney>, <Person: Ringo Starr>]> >>> # This deletes both of the intermediate model instances for Ringo Starr >>> beatles.members.remove(ringo) >>> beatles.members.all() <QuerySet [<Person: Paul McCartney>]>
方法clear()
用于實(shí)例的所有多對(duì)多關(guān)系:
>>> # Beatles have broken up >>> beatles.members.clear() >>> # Note that this deletes the intermediate model instances >>> Membership.objects.all() <QuerySet []>
一旦你建立了自定義多對(duì)多關(guān)聯(lián)關(guān)系,就可以執(zhí)行查詢操作。和一般的多對(duì)多關(guān)聯(lián)關(guān)系一樣,你可以使用多對(duì)多關(guān)聯(lián)模型的屬性來(lái)查詢:
# Find all the groups with a member whose name starts with 'Paul' >>> Group.objects.filter(members__name__startswith='Paul') <QuerySet [<Group: The Beatles>]>
當(dāng)你使用中間模型的時(shí)候,你也可以查詢他的屬性:
# 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)) <QuerySet [<Person: Ringo Starr]>
如果你想訪問(wèn)一個(gè)關(guān)系的信息時(shí)你可以直接查詢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.'
另一種訪問(wèn)同樣信息的方法是通過(guò)Person對(duì)象來(lái)查詢多對(duì)多遞歸關(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.'
使用OneToOneField來(lái)定義一對(duì)一關(guān)系。就像使用其他類(lèi)型的Field一樣:在模型屬性中包含它。
當(dāng)一個(gè)對(duì)象以某種方式“繼承”另一個(gè)對(duì)象時(shí),這那個(gè)對(duì)象的主鍵非常有用。
OneToOneField需要一個(gè)位置參數(shù):與模型相關(guān)的類(lèi)。
例如,當(dāng)你要建立一個(gè)有關(guān)“位置”信息的數(shù)據(jù)庫(kù)時(shí),你可能會(huì)包含通常的地址,電話等分支。然后,如果你想接著建立一個(gè)關(guān)于關(guān)于餐廳的數(shù)據(jù)庫(kù),除了將位置數(shù)據(jù)庫(kù)當(dāng)中的一部分復(fù)制到Restaurant模型,你也可以將一個(gè)指向Place OneToOneField放到Restaurant當(dāng)中(因?yàn)椴蛷d“是一個(gè)”地點(diǎn));事實(shí)上,在處理這樣的情況時(shí)最好使用模型繼承,它隱含的包括了一個(gè)一對(duì)一關(guān)系。
和 ForeignKey一樣,可以創(chuàng)建自關(guān)聯(lián)關(guān)系也可以創(chuàng)建與尚未定義的模型的關(guān)系。
OneToOneField初步還接受一個(gè)可選的parent_link參數(shù)。
OneToOneField類(lèi)通常自動(dòng)的成為模型的主鍵,這條規(guī)則現(xiàn)在不再使用了(而你可以手動(dòng)指定primary_key參數(shù))。因此,現(xiàn)在可以在其中的模型當(dāng)中指定多個(gè)OneToOneField分段。
詳情參考官網(wǎng): https://www.khan.pub/django3.0/index.html
更多建議: