一 ORM基礎(chǔ)知識
1 在同一個模型類中的字段
from django.db import models
class OneModelFields(models.Model):
# 自增長字段,int型
Auto = models.AutoField()
BigAuto = models.BigAutoField()
# 二進(jìn)制數(shù)據(jù)
Binary = models.BinaryField()
# 布爾型
Boolean = models.BooleanField() # 不為空
NullBoolean = models.NullBooleanField() # 允許為空
# 整型
PositiveSmallInteger = models.PositiveSmallIntegerField() # 5個字節(jié)正整數(shù)
SmallInteger = models.SmallIntegerField() # 6個字節(jié)整數(shù)
PositiveInteger = models.PositiveIntegerField() # 10個字節(jié)正整數(shù)
Integer = models.IntegerField() # 11個字節(jié)整數(shù)
BigInteger = models.BigIntegerField() # 20個字節(jié)整數(shù)
# 字符串類型
Char = models.CharField() # 對應(yīng)數(shù)據(jù)庫 varchar
Test = models.TextField() # 對應(yīng)數(shù)據(jù)庫 longtext
# 時間日期類型
Date = models.DateField() # 年月日
DateTime = models.DateTimeField() # 年月日時分秒
Duration = models.DurationField() # 表示一段時間,int型,底層python timedelta實現(xiàn)
# 浮點型
Float = models.FloatField()
Decimal = models.DecimalField()
# 其他字段
Email = models.EmailField()
Image = models.ImageField()
File = models.FileField()
FilePath = models.FilePathField()
URL = models.URLField()
GenericIPAddress = models.GenericIPAddressField()
2 關(guān)系型字段
"""
一對一: OneToOne
多對一: ForeignKey
多對多: ManyToMany
"""
class A(models.Model):
onetoon = models.OneToOneField(OneModelFields)
class B(models.Model):
foreign = models.ForeignKey(A)
class C(models.Model):
manytomany = models.ManyToManyField(B)
3 字段共有的參數(shù)
- db_column: 在數(shù)據(jù)庫中的字段名稱,默認(rèn)和變量同名
- verbose_name: 后臺顯示名稱
- primary_key=True:主鍵
- null=True: 允許字段為空,默認(rèn)False
- blank=True: 提交表單可以為空,默認(rèn)False,此參數(shù)為True,null參數(shù)必須為True
- db_index=True: 設(shè)置索引,默認(rèn)False
- help_text: 表單幫助信息
- editable: 該字段是否可編輯,默認(rèn)為True
- unique: 字段唯一,默認(rèn)False
- default: 默認(rèn)值
class OneModelFields(models.Model): # 表名:appname_onemodelfield
PositiveSmallInteger = models.PositiveSmallIntegerField(db_column="age", verbose_name="年齡")
SmallInteger = models.SmallIntegerField(primary_key=True)
Integer = models.IntegerField(null=True, blank=True)
BigInteger = models.BigIntegerField(unique=True, db_index=True, default=0)
Char = models.CharField(help_text="表單幫助信息")
Test = models.TextField(editable=False)
4 個別字段具有的參數(shù)
字符串型
- max_length: 必須指定數(shù)值的參數(shù),utf8編碼的最大長度
時間日期類型
- unique_for_date: 日期必須唯一
- unique_for_month: 月份必須唯一
- unique_for_year: 年份必須唯一
- auto_now_add: 增加記錄時的時間
- auto_now: 更新當(dāng)前記錄的時間
浮點型
- max_digits: DecimalField字段必須指定,一共多少位
- decimal_places: DecimalField字段必須指定,小數(shù)點位數(shù)
class OneModelFields(models.Model):
# 字符串類型
Char = models.CharField(max_length=100) # 對應(yīng)數(shù)據(jù)庫 varchar
Test = models.TextField() # 對應(yīng)數(shù)據(jù)庫 longtext
# 時間日期類型
Date = models.DateField(unique_for_date=True, auto_now=True) # 年月日
DateTime = models.DateTimeField(unique_for_year=True, unique_for_month=True, auto_now_add=True) # 年月日時分秒
Duration = models.DurationField() # 表示一段時間,int型,底層python timedelta實現(xiàn)
# 浮點型
Float = models.FloatField()
Decimal = models.DecimalField(max_length=4, decimal_places=2) # 例如 12.11
5 關(guān)系型字段參數(shù)
class A(models.Model):
""" related_name: 反向查詢,父表查子表
子表A,父表OneModelFields
通過OneModelFields查詢A的數(shù)據(jù)
"""
onetoon = models.OneToOneFields(OneModelFields, related_name="one")
class B(models.Model):
"""on_delete 的六種操作
1. models.CASCADE: 將定義有外鍵的模型對象同時刪除 ,django模板的默認(rèn)操作
2. model.PROTECT: 阻止上面的刪除操作,但是彈出ProtectedError異常
3. models.SET_NULL: 將外鍵字段設(shè)為null,只有當(dāng)字段設(shè)置了null=True時,方可使用該值
4. models.SET_DEFAULT: 將外鍵字段設(shè)為默認(rèn)值,只有當(dāng)字段設(shè)置了default參數(shù)時,方可使用
5. models.DO_NOTHING: 什么也不做
6. models.SET: 設(shè)置為一個傳遞給SET()的值或者一個回調(diào)函數(shù)的返回值,注意大小寫
"""
foreign = models.ForeignKey(A, on_delete=models.CASCADE) # 刪除級聯(lián)
foreign = models.ForeignKey(A, on_delete=models.PROTECT)
foreign = models.ForeignKey(A, on_delete=models.SET_NULL, null=True, blank=True) # 刪除置空
foreign = models.ForeignKey(A, on_delete=models.SET_DEFAULT, default=0)
foreign = models.ForeignKey(A, on_delete=models.DO_NOTHING)
foreign = models.ForeignKey(A, on_delete=models.SET)
6 自關(guān)聯(lián)
class AddressInfo(models.Model):
""" 地址信息
id:記錄主鍵,會自動生成
address:存儲省、市或者縣(區(qū))的名稱:
pid:存儲本條信息關(guān)聯(lián)的一條記錄id
例如:一條記錄為:id=0, address="江蘇省", pid=null
另外一條為:id=1, address="南京市", pid=0
再來一條: id=2, address="江寧區(qū)", pid=1
"""
address = models.CharField(max_length=200, null=True, blank=True, verbose_name="地址")
pid = models.ForeignKey('self', null=True, blank=True, verbose_name="自關(guān)聯(lián)字段")
def __str__(self):
return self.address
7 元數(shù)據(jù)Mate
class AddressInfos(models.Model):
address = models.CharField(max_length=200, null=True, blank=True, verbose_name="地址")
pid = models.ForeignKey('self', null=True, blank=True, verbose_name="自關(guān)聯(lián)字段")
note = models.CharField(max_length=200, null=True, blank=True, verbose_name="說明")
def __str__(self):
return self.address
class Meta:
db_table = "addressinfo" # 表的名稱
ordering = 'pid' # 排序字段
verbose_name = "省市縣地址信息"
verbose_name_plural = verbose_name # 復(fù)數(shù)
# abstract = True # 基類用于繼承,默認(rèn)為False
unique_together = ("address", "note") # 聯(lián)合唯一健,還可以用二維元組 ((), ())
app_label = 'app_name' # 模型類屬于哪一個應(yīng)用
# db_tablespace # 定義數(shù)據(jù)庫表空間的名稱
二 模型類開發(fā)實例
以慕課網(wǎng)為例,抽象出四張表,關(guān)系如下

image.png
以上模型對應(yīng)的model部分如下:
from django.db import models
class Teacher(models.Model):
"""
講師信息表
"""
nickname = models.CharField(max_length=30, primary_key=True, db_index=True, verbose_name="昵稱")
introduction = models.TextField(default="這位同學(xué)很懶,么有簽名的說~", verbose_name="簡介")
fans = models.PositiveIntegerField(default=0, verbose_name="粉絲數(shù)")
created_at = models.DateTimeField(auto_now_add=True, verbose_name="創(chuàng)建時間")
updated_at = models.DateTimeField(auto_now=True, verbose_name="更新時間")
class Meta:
verbose_name = "講師信息表"
verbose_name_plural = verbose_name
def __str__(self):
return self.nickname
class Course(models.Model):
"""
課程信息表
"""
title = models.CharField(max_length=100, primary_key=True, db_index=True, verbose_name="課程名")
type = models.CharField(choices=((1, "實戰(zhàn)課"), (2, "免費(fèi)課"), (0, "其他")), max_length=1, default=0, verbose_name="課程類型")
price = models.PositiveSmallIntegerField(verbose_name="價格")
volume = models.BigIntegerField(verbose_name="銷量")
online = models.DateField(verbose_name="上線時間")
created_at = models.DateTimeField(auto_now_add=True, verbose_name="創(chuàng)建時間")
updated_at = models.DateTimeField(auto_now=True, verbose_name="更新時間")
# 多對一的關(guān)系字段
# 當(dāng)講師被刪除時,刪除講師的課程
teacher = models.ForeignKey(Teacher,null=True, blank=True, on_delete=models.CASCADE, verbose_name="課程的教師") # 刪除級聯(lián)
class Meta:
verbose_name = "課程信息表"
verbose_name_plural = verbose_name
def __str__(self):
return f"{self.get_type_display()}-{self.title}" # 示例:實戰(zhàn)課-django零基礎(chǔ)入門
class Student(models.Model):
"""
"學(xué)生信息表"
"""
nickname = models.CharField(max_length=30, primary_key=True, db_index=True, verbose_name="昵稱")
age = models.PositiveSmallIntegerField(verbose_name="年齡")
gender = models.CharField(choices=((1, "男"), (2, "女"), (0, "保密")), default=0, max_length=1, verbose_name="性別")
study_time = models.PositiveIntegerField(default="0", verbose_name="學(xué)習(xí)時長(h)")
created_at = models.DateTimeField(auto_now_add=True, verbose_name="創(chuàng)建時間")
updated_at = models.DateTimeField(auto_now=True, verbose_name="更新時間")
# 多對多的關(guān)系字段
course = models.ManyToManyField(Course, verbose_name="學(xué)生學(xué)習(xí)的課程")
class Meta:
verbose_name = "學(xué)生信息表"
verbose_name_plural = verbose_name
def __str__(self):
return self.nickname
class TeacherAssistant(models.Model):
"""
助教信息表
"""
nickname = models.CharField(max_length=30, primary_key=True, db_index=True, verbose_name="昵稱")
hobby = models.CharField(max_length=100, null=True, blank=True, verbose_name="愛好")
created_at = models.DateTimeField(auto_now_add=True, verbose_name="創(chuàng)建時間")
updated_at = models.DateTimeField(auto_now=True, verbose_name="更新時間")
# 一對一的關(guān)系字段
teacher = models.OneToOneField(Teacher,null=True, blank=True, on_delete=models.SET_NULL, verbose_name="助教對應(yīng)的教師") # 刪除置空
class Meta:
verbose_name = "助教信息表"
verbose_name_plural = verbose_name
def __str__(self):
return self.nickname