- model是Django中的數(shù)據(jù)模型
- 每個(gè)model都是繼承自django.db.models.Model的子類
- 每個(gè)model都映射一個(gè)數(shù)據(jù)表
- model中的每個(gè)類屬性對(duì)應(yīng)著數(shù)據(jù)表中的一列
- django支持ORM
- 創(chuàng)建model并進(jìn)行migrate后
- Django會(huì)自動(dòng)生成表名(可以自定義)
- Django會(huì)自動(dòng)增加主鍵一列(可以自定義)
- Django會(huì)根據(jù)不同數(shù)據(jù)庫(kù)創(chuàng)建不同的SQL語(yǔ)句
-
Field中的常見選項(xiàng)
- null:允許該列數(shù)據(jù)為空(默認(rèn)為False)
- blank:主要用于是否允許表單為空(默認(rèn)為False)
- choices:為一個(gè)Field提供可選項(xiàng)(并且默認(rèn)生成的表單為一個(gè)選項(xiàng))
from django.db import models class Person(models.Model): # choices的對(duì)象是一個(gè)可迭代對(duì)象移层,其元素為‘含有兩個(gè)元素的元組’ SHIRT_SIZES = ( ('S', 'Small'), ('M', 'Medium'), ('L', 'Large'), ) name = models.CharField(max_length=60) shirt_size = models.CharField(max_length=1, choices=SHIRT_SIZES) # choice API >>> p = Person(name="Fred Flintstone", shirt_size="L") >>> p.save() >>> p.shirt_size 'L' >>> p.get_shirt_size_display() # get_FOO_display()方法可以顯示具體內(nèi)容 'Large'
- default:既可以是一個(gè)數(shù)值對(duì)象墓贿,也可以是一個(gè)可調(diào)用對(duì)象
- help_text:在生成的表單中展示‘幫助’信息
- primary_key:將某一列設(shè)置為主鍵(該列變?yōu)橹蛔x)竖配;默認(rèn)為False,即Django會(huì)自動(dòng)創(chuàng)建一個(gè)整型主鍵
- unique:該列中的每個(gè)數(shù)據(jù)必須獨(dú)一無(wú)二(默認(rèn)為False)
- 自動(dòng)生成主鍵
默認(rèn)情況下乳愉,如果不顯式指定主鍵,Django會(huì)在model中自動(dòng)添加以下屬性id = models.AutoField(primary_key=True)
- 顯式指定列名
對(duì)于非關(guān)系型列(即非ForeignKeyField,ManyToManyField蕾总,OneToOneField)戴尸,第一個(gè)位置參數(shù)為空時(shí)粟焊,將默認(rèn)屬性名為列名;否則使用位置參數(shù)作為列名
對(duì)于關(guān)系型列孙蒙,需要指定位置參數(shù)以表明關(guān)聯(lián)的數(shù)據(jù)表# 列名為"person's first name" first_name = models.CharField("person's first name", max_length=30) # 列名為"first_name" first_name = models.CharField(max_length=30) # 關(guān)聯(lián)表為"Poll" poll = models.ForeignKey( Poll, on_delete=models.CASCADE, verbose_name="the related poll", )
- 關(guān)聯(lián)
- Many-to-one 關(guān)聯(lián)
使用django.db.models.ForeignKey项棠,第一個(gè)位置參數(shù)需要指定關(guān)聯(lián)表名 - Many-to-many 關(guān)聯(lián)
使用django.db.models.ManyToManyField(相關(guān)的兩個(gè)表中,只需要在一個(gè)表中指定即可)
可以顯式的創(chuàng)建many-to-many的關(guān)聯(lián)數(shù)據(jù)表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) # 通過(guò)through指定關(guān)聯(lián)表 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)
- One-to-one 關(guān)聯(lián)
使用django.db.models.OneToOneField马篮,可以用于擴(kuò)展某一model
- Many-to-one 關(guān)聯(lián)
-
Meta 選項(xiàng)
Model的Meta中保存著所有非列的屬性(比如ordering(默認(rèn)排序)沾乘、db_table(數(shù)據(jù)表名稱)等等)from django.db import models class Ox(models.Model): horn_length = models.IntegerField() # class Meta 是可選項(xiàng) class Meta: ordering = ["horn_length"] verbose_name_plural = "oxen"
- Model 的方法
我們可以在Model中自定義方法,也可以使用或者重載Model中已有的方法
有兩個(gè)方法在大多數(shù)情況下需要我們自己定義- __ str__()
- get_absolute_url()
該方法告訴Django如何得到一個(gè)對(duì)象的URL(一般使用django的reverse()函數(shù))def get_absolute_url(self): from django.urls import reverse return reverse('people.views.details', args=[str(self.id)])
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() # 關(guān)鍵在于對(duì)Model.save()方法的繼承上浑测,另外通過(guò)使用(*args, **kwargs)參數(shù)可以自動(dòng)獲取相關(guān)參數(shù) super(Blog, self).save(*args, **kwargs) # Call the "real" save() method. do_something_else()
- Model的繼承
django中存在三種繼承- Abstract base classes
- Multitable inheritance
- Proxy models
- Abstract base classes
在class Meta中設(shè)置abstract = True翅阵,就可以將該model變?yōu)槌橄箢悺擃愔卸x的列屬性可以被子類所繼承而無(wú)需重新定義歪玲,且class Meta中的屬性亦會(huì)被繼承(除了abstract = True)
Abstract base classes并不會(huì)產(chǎn)生數(shù)據(jù)表,也不能直接用于創(chuàng)建實(shí)例
為了指定子類關(guān)聯(lián)表列的relate_name掷匠,可以在abc類的關(guān)聯(lián)表列中進(jìn)行設(shè)置from django.db import models class CommonInfo(models.Model): name = models.CharField(max_length=100) age = models.PositiveIntegerField() # 將CommonInfo聲明為一個(gè)abc類 class Meta: abstract = True ordering = ['name'] class Student(CommonInfo): # Student 類自動(dòng)繼承name和age列 home_group = models.CharField(max_length=5) class Meta: # Student 類會(huì)繼承CommonInfo中的Meta的信息 # 不過(guò)在此之前會(huì)自動(dòng)設(shè)置abstract=False(當(dāng)然也可以自己顯式地設(shè)置abstract=True從而成為abc類) db_table = 'student_info'
# common/models.py from django.db import models class Base(models.Model): m2m = models.ManyToManyField( OtherModel, # 若不設(shè)置related_name滥崩,則默認(rèn)為"子類名 + '_set'" # %(app_label)s 指代當(dāng)前應(yīng)用名稱 # %(class)s 指代當(dāng)前類的類名 related_name="%(app_label)s_%(class)s_related", related_query_name="%(app_label)s_%(class)ss", ) class Meta: abstract = True # OtherModel 使用 ChildA 類時(shí)的屬性名將是'common_childa_related' class ChildA(Base): pass class ChildB(Base): pass
- Multi-table inheritance
父類和子類都可以生成數(shù)據(jù)表,且子類會(huì)繼承父類的類屬性(列屬性)讹语,但父類和子類是兩個(gè)不同的表
此外钙皮,不同于abc類,子類不會(huì)繼承父類class Meta中的屬性 - Proxy models
Proxy model用于當(dāng)你只想為一個(gè)表增加一些方法或者M(jìn)eta屬性顽决,而不想改變?cè)璵odel的代碼時(shí)from django.db import models class Person(models.Model): first_name = models.CharField(max_length=30) last_name = models.CharField(max_length=30) class MyPerson(Person): class Meta: # 指定該類為Person的代理數(shù)據(jù)模型 proxy = True # 在該proxy model中可以增加一個(gè)額外的Meta屬性 odering = ['last_name'] # 在該proxy model中可以增加一些額外的方法 def do_something(self): # ... pass # 需要注意的一點(diǎn)是Person和MyPerson類都可以調(diào)用Person數(shù)據(jù)表中的數(shù)據(jù) # 不同之處在于通過(guò)Person類創(chuàng)建/查找到的實(shí)例中沒(méi)有ordering屬性短条,也不能調(diào)用do_something方法