2-django的模型
概述:Django對各種數(shù)據(jù)庫都提供了很好的支持,Django為這些數(shù)據(jù)庫提供了統(tǒng)一的調(diào)用接口API,程序員可以根據(jù)自己的業(yè)務(wù)需求選擇不同的數(shù)據(jù)庫
ORM簡介概述:對象-關(guān)系-映射
作用:?根據(jù)類生成表結(jié)構(gòu);將對象、列表的操作轉(zhuǎn)換成對應(yīng)的SQL語句;將SQL語句查詢到的結(jié)果轉(zhuǎn)換為對象或者列表
優(yōu)點(diǎn):極大的減輕開發(fā)人員的工作量,不需要面對因數(shù)據(jù)庫的變更而導(dǎo)致代碼無效在修改代碼, 防止sql注入攻擊
圖解:
定義模型
模型、屬性、表、字段之間的關(guān)系:一個模型在數(shù)據(jù)庫中對應(yīng)一張表,在模型中定義的屬性對應(yīng)該模型對照表中的一個字段
創(chuàng)建模型類班級類
class Grade(models.Model): name = models.CharField(max_length=20) boyNum = models.IntegerField() girlNum = models.IntegerField() isDelete = models.BooleanField(default=False) def __str__(self): return self.name
學(xué)生類
class Student(models.Model): name = models.CharField(max_length=20) sex = models.BooleanField() age = models.IntegerField() contend = models.CharField(max_length=40) # 關(guān)聯(lián)類名的小寫或直接類名 Grade grade = models.ForeignKey("grade") isDelete = models.BooleanField(default=False) def __str__(self): return self.name字段類型和字段選項(xiàng)
字段類型 ·AutoField ·一個根據(jù)實(shí)際ID自動增長的IntegerField,通常不指定如果不指定,一個主鍵字段將自動添加到模型中 ·CharField(max_length=字符長度) ·字符串,默認(rèn)的表單樣式是 TextInput ·TextField ·大文本字段,一般超過4000使用,默認(rèn)的表單控件是Textarea ·IntegerField ·整數(shù) ·DecimalField(max_digits=None, decimal_places=None) ·使用python的Decimal實(shí)例表示的十進(jìn)制浮點(diǎn)數(shù) ·參數(shù)說明 ·DecimalField.max_digits ·位數(shù)總數(shù) ·DecimalField.decimal_places ·小數(shù)點(diǎn)后的數(shù)字位數(shù) ·FloatField ·用Python的float實(shí)例來表示的浮點(diǎn)數(shù) ·BooleanField ·true/false 字段,此字段的默認(rèn)表單控制是CheckboxInput ·NullBooleanField ·支持null、true、false三種值 ·DateField(auto_now=False, auto_now_add=False) ·使用Python的datetime.date實(shí)例表示的日期 ·參數(shù)說明 ·DateField.auto_now ·每次保存對象時,自動設(shè)置該字段為當(dāng)前時間,用于"最后一次修改"的時間戳,它總是使用當(dāng)前日期, 默認(rèn)為false ·DateField.auto_now_add ·當(dāng)對象第一次被創(chuàng)建時自動設(shè)置當(dāng)前時間,用于創(chuàng)建的時間戳,它總是使用當(dāng)前日期,默認(rèn)為false ·說明 ·該字段默認(rèn)對應(yīng)的表單控件是一個TextInput. 在管理員站點(diǎn)添加了一個JavaScript寫的日歷控件,和一 個“Today"的快捷按鈕,包含了一個額外的invalid_date錯誤消息鍵 ·注意 ·auto_now_add, auto_now, and default 這些設(shè)置是相互排斥的,他們之間的任何組合會發(fā)生錯誤的結(jié)果 ·TimeField ·使用Python的datetime.time實(shí)例表示的時間,參數(shù)同DateField ·DateTimeField ·使用Python的datetime.datetime實(shí)例表示的日期和時間,參數(shù)同DateField ·FileField ·一個上傳文件的字段 ·ImageField ·繼承了FileField的所有屬性和方法,但對上傳的對象進(jìn)行校驗(yàn),確保它是個有效的image
字段選項(xiàng) ·概述 ·通過字段選項(xiàng),可以實(shí)現(xiàn)對字段的約束 ·在字段對象時通過關(guān)鍵字參數(shù)指定 ·null ·如果為True,Django 將空值以NULL存儲到數(shù)據(jù)庫中,默認(rèn)值是 False ·blank ·如果為True,則該字段允許為空白,默認(rèn)值是 False ·注意 ·null是數(shù)據(jù)庫范疇的概念,blank是表單驗(yàn)證證范疇的 ·db_column ·字段的名稱,如果未指定,則使用屬性的名稱 ·db_index ·若值為 True, 則在表中會為此字段創(chuàng)建索引 ·default ·默認(rèn)值 ·primary_key ·若為 True, 則該字段會成為模型的主鍵字段 ·unique ·如果為 True, 這個字段在表中必須有唯一值模型之間的關(guān)系
模型關(guān)系 ·分類 ·ForeignKey:一對多,將字段定義在多的端中 ·ManyToManyField:多對多,將字段定義在兩端中 ·OneToOneField:一對一,將字段定義在任意一端中 ·用一訪問多 ·格式 對象.模型類小寫_set ·示例 grade.students_set ·用一訪問一 ·格式 ·對象.模型類小寫 ·示例 ·grade.students ·訪問id ·格式 ·對象.屬性_id ·示例 ·student.sgrade_id元選項(xiàng)
在模型類中定義一個Meta類,用于設(shè)置元信息
class Student(models.Model): name = models.CharField(max_length=20) sex = models.BooleanField() age = models.IntegerField() contend = models.CharField(max_length=40) # 關(guān)聯(lián)類名的小寫 grade = models.ForeignKey("grade") isDelete = models.BooleanField(default=False) def __str__(self): return self.name class Meta(): db_table = "students" ordering = ["-id"]
屬性
db_table: 定義數(shù)據(jù)表名,推薦使用類名小寫,并且添加復(fù)數(shù)
ordering: 規(guī)定對象的默認(rèn)排序字段 ; ordering = ["id"]: 正序; ordering = ["-id"]: 倒序;
注意:排序會增加數(shù)據(jù)庫的開銷
模型成員 objects對象概述: 是Manager類型的對象,用于與數(shù)據(jù)庫進(jìn)行交互; 當(dāng)定義模型時沒有指定管理器,則Django會為模型提供一個名為objects的管理器
自定義模型管理器class Student(models.Model): #自定義模型管理器 myobject = models.Manager() name = models.CharField(max_length=20) sex = models.BooleanField() age = models.IntegerField() contend = models.CharField(max_length=40) # 關(guān)聯(lián)類名的小寫 grade = models.ForeignKey("grade") isDelete = models.BooleanField(default=False) def __str__(self): return self.name class Meta(): db_table = "students" ordering = ["-id"]
注意:?如果為模型指定了管理器,那么Django不再為模型類提供名為objects的管理器
自定義模型管理器類class StudentManager(models.Manager): def get_queryset(self): return super(StudentManager, self).get_queryset().filter(isDelete=False) class Student(models.Model): #自定義模型管理器 objects = StudentManager()
get_queryset獲取查詢集(數(shù)據(jù)集),自定義管理器類調(diào)用父類中的get_queryset方法后在進(jìn)行過濾
創(chuàng)建對象當(dāng)創(chuàng)建對象時,Django不會對數(shù)據(jù)庫進(jìn)行讀寫操作。調(diào)用save()方法才與數(shù)據(jù)庫進(jìn)行交互,將對象存儲到數(shù)據(jù)庫中。__init__方法已經(jīng)在基類models.Model中使用,在自定義模型類中無法使用
在模型類中增加一個類方法:
class Student(models.Model): #自定義模型管理器 objects = StudentManager() name = models.CharField(max_length=20) sex = models.BooleanField() age = models.IntegerField() contend = models.CharField(max_length=40) grade = models.ForeignKey(Grade) isDelete = models.BooleanField(default=False) def __str__(self): return self.name class Meta(): db_table = "students" ordering = ["-id"] #類方法,類可以直接調(diào)用 創(chuàng)建對象可以直接寫 Student.create("ray",1,18,....) @classmethod def create(cls, name, sex, age, contend, grade): return cls(name=name, sex=sex, age=age, contend=contend, grade=grade)
在自定義模型器類中增加一個方法
class StudentManager(models.Manager): def get_queryset(self): return super(StudentManager, self).get_queryset().filter(isDelete=False) def create(self, name, sex, age, contend, grade): obj = self.model() obj.name = name obj.sex = sex obj.age = age obj.contend = contend obj.grade = grade return obj查詢數(shù)據(jù)
查詢集:表示從數(shù)據(jù)庫中獲取的對象集合,查詢集可以含有一個或者多個過濾器
過濾器:基于所給的參數(shù)限制查詢集的結(jié)果,得到新的查詢集
從SQL的角度,查詢集合select語句等價,過濾器就像where和limit子句相似
查詢集在管理器上調(diào)用過濾器方法或者是其他數(shù)據(jù)查詢集上調(diào)用過濾器方法得到新的查詢集
查詢集經(jīng)過過濾器篩選得到新的查詢集,因此可以使用鏈?zhǔn)秸Z法結(jié)構(gòu)
惰性查詢:創(chuàng)建查詢集不會帶來任何的數(shù)據(jù)庫訪問,直到調(diào)用數(shù)據(jù)時,才會訪問數(shù)據(jù)庫
什么時候?qū)Σ樵兗笾担?迭代、序列化、與if合用
返回查詢集的方法 all()返回查詢集的方法
def students(request): stus = Student.objects.all() return render(request, "students.html", {"stus":stus})filter()
作用:將符合條件的數(shù)據(jù)過濾進(jìn)來
使用:filter(鍵1=值1, 鍵2=值2);filter(鍵1=值1, 鍵2=值2)
def students(request): stus = Student.objects.filter(age=20) return render(request, "students.html", {"stus":stus})exclude()
作用: 將符合條件的數(shù)據(jù)過濾出去
def students(request): stus = Student.objects.exclude(age=20) return render(request, "students.html", {"stus":stus})order_by()
作用:排序
def students(request): stus = Student.objects.order_by("age") return render(request, "students.html", {"stus":stus}) def students(request): stus = Student.objects.order_by("-age") return render(request, "students.html", {"stus":stus})values()
作用: 一個對象構(gòu)成一個字典,然后構(gòu)成一個列表返回
def students(request): stus = Student.objects.values() print(stus) return render(request, "students.html", {"stus":stus})返回單個值的方法 get()
作用: 返回單個滿足條件的對象
def students(request): # pk代表主鍵 try: stus = [Student.objects.get(age=20)] except Student.DoesNotExist as e: pass except Student.MultipleObjectsReturned as e: pass return render(request, "students.html", {"stus":stus})
注意: 如果多條數(shù)據(jù)被返回,會引發(fā) “類名.MultipleObjectsReturned” 異常;數(shù)據(jù)不存在會報(bào) "類名.DoesNotExist" 異常
count()返回當(dāng)前查詢的總條數(shù)
first()返回查詢集中的第一個對象
last()返回查詢集中的最后一個對象
exists()判斷查詢集中是否有數(shù)據(jù),如果有返回True,否則返回False
def students(request): stus = Student.objects.filter(age=20) if stus.exists(): return render(request, "students.html", {"stus":stus}) else: return HttpResponse("沒有學(xué)生數(shù)據(jù)")限制查詢集
查詢集返回列表,可以使用下標(biāo)的方式進(jìn)行限制,等同于SQL中的limit和offset子句
注意: 不支持負(fù)數(shù)索引; 使用下標(biāo)后返回一個新的查詢集,不會立即執(zhí)行查詢字段查詢
def students(request): stus = Student.objects.all()[5:10]#[0:5) return render(request, "students.html", {"stus":stus})字段查詢 概述
實(shí)現(xiàn)where語句,作為filter()、exclude()、get()的參數(shù)
語法 : 屬性名稱__比較運(yùn)算符=值 (注意:里面有兩個下劃線)
外鍵: 使用 “屬性名_id” 表示原始的外鍵值
轉(zhuǎn)義: like語句中使用%,可以直接使用
比較運(yùn)算符exact: 表示判斷相當(dāng),大小寫敏感
contains: 是否包含,大小寫敏感
# 找描述中帶有"ray"的所有學(xué)生 def students(request): stus = Student.objects.filter(contend__icontains="sunck") return render(request, "students.html", {"stus":stus})
startswith、endswith: 以value開頭、結(jié)尾,大小寫敏感
# 找描述以ray開頭的所有學(xué)生 def students(request): stus = Student.objects.filter(contend__startswith="ray") return render(request, "students.html", {"stus":stus})
iexact、icontains、istartswith、iendswith: 不區(qū)分大小寫
isnull, isnotnull : 是否為空, 是否為非空
in : 包含在范圍之內(nèi)
# 找id為2,5,8,9的學(xué)生 def students(request): stus = Student.objects.filter(pk__in=[2,5,8,9]) return render(request, "students.html", {"stus":stus})
gt, gte, lt, lte
# 找年齡大于等于20的所有學(xué)生 def students(request): stus = Student.objects.filter(age__gte=20) return render(request, "students.html", {"stus":stus})
year、month、day、week_day、hour、minute、second: 對日期類型的屬性進(jìn)行運(yùn)算
跨關(guān)聯(lián)關(guān)系的查詢處理join查詢:
語法:關(guān)聯(lián)的模型類名小寫__屬性名__比較運(yùn)算符=值
注意: __比較運(yùn)算符 沒有,表示等于; 可以反向使用,即關(guān)聯(lián)的兩個模型中都可以使用
# 描述中帶有ray的學(xué)生屬于那些班級 def students(request): grades = Grade.objects.filter(student__contend__contains="ray") print(grades) stus = Student.objects.all() return render(request, "students.html", {"stus":stus})
查詢的快捷方式: pk pk表示主鍵,默認(rèn)主鍵是id
聚合函數(shù)注意: 使用aggregate()函數(shù)返回聚合函數(shù)的值
函數(shù): Avg、Count、Max、Min、Sum
# 求所有人的年齡的和 from django.db.models import Sum def students(request): age = Student.objects.aggregate(Sum("age")) print("***********", age) stus = Student.objects.all() return render(request, "students.html", {"stus":stus})F對象
作用: 可以使模型中的A字段與B字段進(jìn)行比較,如果A字段出現(xiàn)在等號的左側(cè),那么B字段使用F對象寫在等號右側(cè)
# 找男生個數(shù)多于女生個數(shù)的班級 from django.db.models import F def students(request): grades = Grade.objects.filter(boyNum__gt=F("girlNum")) print(grades) stus = Student.objects.all() return render(request, "students.html", {"stus":stus})
F對象可以進(jìn)行數(shù)學(xué)運(yùn)算
from django.db.models import F def students(request): grades = Grade.objects.filter(boyNum__gt=F("girlNum")*2) print(grades) stus = Student.objects.all() return render(request, "students.html", {"stus":stus})
F對象還可以進(jìn)行關(guān)聯(lián)查詢 模型類小寫__屬性名
# 沒有被刪除的學(xué)生的班級 from django.db.models import F def students(request): grades = Grade.objects.filter(isDelete=F("student__isDelete")) print(grades) stus = Student.objects.all() return render(request, "students.html", {"stus":stus})
對于data/time字段,可以進(jìn)行timedelta()進(jìn)行運(yùn)算
Q對象 邏輯與# 年齡大于等于20且小于等于50的學(xué)生 def students(request): stus = Student.objects.filter(age__gte=20,age__lte=50) return render(request, "students.html", {"stus":stus}) def students(request): stus = Student.objects.filter(age__gte=20).filter(age__lte=50) return render(request, "students.html", {"stus":stus}) from django.db.models import Q def students(request): stus = Student.objects.filter(Q(age__gte=20) & Q(age__lte=50)) return render(request, "students.html", {"stus":stus})邏輯或
# 獲取年齡小于20或者年齡大于50的學(xué)生 from django.db.models import Q def students(request): stus = Student.objects.filter(Q(age__lt=20) | Q(age__gt=50)) return render(request, "students.html", {"stus":stus})邏輯非
# 獲取年齡不大于等于20的學(xué)生 def students(request): stus = Student.objects.filter(age__lt=20) return render(request, "students.html", {"stus":stus}) from django.db.models import Q def students(request): stus = Student.objects.filter(~Q(age__gte=20)) return render(request, "students.html", {"stus":stus})
注意: 過濾器函數(shù)中可以混合使用Q對象和關(guān)鍵字參數(shù),所有參數(shù)條件都將and在一起,Q對象必須位于關(guān)鍵字參數(shù)的前面
def students(request): stus = Student.objects.all()[5:10]#[0:5) return render(request, "students.html", {"stus":stus})模型關(guān)系 1-1
使用場景: 表的字段太多,需要拆分
# 人 class Person(models.Model): name = models.CharField(max_length=20) age = models.IntegerField() # 關(guān)系存放在哪張表都可以 # 綁定身份證與人的一對一關(guān)系,默認(rèn)情況下當(dāng)刪身份證時綁定的人也可以刪除,通過on_delete屬性設(shè)置 idCard = models.OneToOneField(IDCard) # 身份證 class IDCard(models.Model): sex = models.BooleanField() num = models.CharField(max_length=20)
主表從表: 聲明關(guān)系的表為從表
級聯(lián)數(shù)據(jù)獲?。?/p>
從獲取主:
關(guān)系是直接聲明的,是一個顯性的屬性
獲取pk為1的人的身份證號
per = Person.objects.get(pk=1) print(per.idCard.num)
主獲取從:
關(guān)系字段是隱性屬性,對象.關(guān)系模型類名的小寫
獲取身份證號是1的人的姓名
card = IDCard.objects.get(pk=1) print(card.person.name)
1-n一對多,也就是外鍵。
主表從表: 聲明關(guān)系的表為從表(ForeignKey)。
級聯(lián)數(shù)據(jù)獲取:
從獲取主: 關(guān)系是直接聲明的,是一個顯性的屬性
主獲取從: 關(guān)系字段是隱性屬性,對象.模型類小寫_set
#找到1班的所有學(xué)生 grade = Grade.objects.get(pk=1) print(grade.student_set.all())m-n
原理: 底層是通過兩個外鍵實(shí)現(xiàn),兩個外鍵存在于另一張關(guān)系表中
#多對多 class Buyer(models.Model): name = models.CharField(max_length=20) level = models.IntegerField() class Product(models.Model): name = models.CharField(max_length=20) price = models.IntegerField() #關(guān)系形成 buyers = models.ManyToManyField(Buyer)
形成關(guān)系
def ptob(reqeust, p, b): product = Product.objects.get(pk=p) buyer = Buyer.objects.get(pk=b) #產(chǎn)生關(guān)聯(lián) product.buyers.add(buyer) return HttpResponse("購買成功")
數(shù)據(jù)級聯(lián)獲取
從獲取主
對象.顯性屬性,得到的是一個數(shù)據(jù)集合,可以進(jìn)行過濾
已知一件商品,獲取該商品所有的購買者
product = Product.objects.get(pk=1) print(product.buyers.all())
主獲取從:
隱性屬性 對象.關(guān)聯(lián)類名小寫_set 得到的是一個數(shù)據(jù)集合,可以進(jìn)行過濾
已知一個購買者,獲取他所買的所有商品
buyer = Buyer.objects.get(pk=1) print(buyer.product_set.all())
模型繼承使用最原始的python類的繼承方式
class Animal(models.Model): name = models.CharField(max_length=20) age = models.IntegerField() class Cat(Animal): weight = models.IntegerField() class Dog(Animal): height = models.IntegerField()
注意: 默認(rèn)繼承方式不是很合理
父類也會對應(yīng)一張表
默認(rèn)在父類中定義的字段會存在父類表中,子類的數(shù)據(jù)通過外鍵關(guān)聯(lián)父表中數(shù)據(jù),子類只有特殊的數(shù)據(jù)在子表中
效率比較低
Django中的數(shù)據(jù)庫模塊提供了一個非常不錯的功能,就是支持models的面向?qū)ο螅梢栽贛eta類中指定是否抽象,然后繼承
class Animal(models.Model): name = models.CharField(max_length=20) age = models.IntegerField() class Meta(): # 讓該類抽象,抽象的父類不會再生產(chǎn)數(shù)據(jù)表 # 子類會繼承父類中的通用數(shù)據(jù),復(fù)制到子表中 abstract = True class Cat(Animal): weight = models.IntegerField() class Dog(Animal): height = models.IntegerField()
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/42241.html
概述:Django對各種數(shù)據(jù)庫都提供了很好的支持,Django為這些數(shù)據(jù)庫提供了統(tǒng)一的調(diào)用接口API,程序員可以根據(jù)自己的業(yè)務(wù)需求選擇不同的數(shù)據(jù)庫 ORM簡介 概述:對象-關(guān)系-映射 作用: 根據(jù)類生成表結(jié)構(gòu);將對象、列表的操作轉(zhuǎn)換成對應(yīng)的SQL語句;將SQL語句查詢到的結(jié)果轉(zhuǎn)換為對象或者列表 優(yōu)點(diǎn):極大的減輕開發(fā)人員的工作量,不需要面對因數(shù)據(jù)庫的變更而導(dǎo)致代碼無效在修改代碼 圖解: showIm...
摘要:簡介是一個開放源代碼的應(yīng)用框架,由寫成,初次發(fā)布于年月,并于年月發(fā)布了第一個正式版本是一種軟件設(shè)計(jì)典范,核心思想是解耦優(yōu)點(diǎn)降低各功能模塊之間的耦合性,方便變更,更容易重構(gòu)代碼,最大程度上實(shí)現(xiàn)了代碼重用圖解模型是應(yīng)用程序中用于處理程序邏輯的部 Django簡介 Django是一個開放源代碼的Web應(yīng)用框架,由python寫成,初次發(fā)布于2005年7月,并于2008年9月發(fā)布了第一個正式版...
摘要:利用開發(fā)個小型商城我們本期的教程是教大家如何利用開發(fā)一個小型的商城這里所說的小型商城只是功能上的簡樸。并于年月在許可證下發(fā)布。這套框架是以比利時的吉普賽爵士吉他手來命名的。是重量級選手中最有代表性的一位。 利用Django開發(fā)個小型商城 我們本期的教程是教大家如何利用Django開發(fā)一個小型的商城,這里所說的小型商城只是功能上的簡樸。 作者:黃志成(小黃) 作者博客:博客地址 前提 1...
摘要:內(nèi)部結(jié)構(gòu)時,頁面發(fā)生錯誤會直接拋給前臺,便于程序員進(jìn)行修改。,用戶新建了需要在該欄目下進(jìn)行注冊。拓展閱讀圖解筆記基礎(chǔ)教程自強(qiáng)學(xué)堂備注該筆記源自網(wǎng)易微專業(yè)開發(fā)節(jié)本文由創(chuàng)作采用知識共享署名中國大陸許可協(xié)議進(jìn)行許可。 Why Django 在一定的時間內(nèi),有限的技術(shù)情況下,建設(shè)一個高質(zhì)量的網(wǎng)站,Django幾乎成了唯一的方案。Django把所有可能性都考慮到了,從這種程度上看復(fù)雜就意味著全面...
閱讀 3464·2023-04-25 19:39
閱讀 3817·2021-11-18 13:12
閱讀 3642·2021-09-22 15:45
閱讀 2441·2021-09-22 15:32
閱讀 726·2021-09-04 16:40
閱讀 3739·2019-08-30 14:11
閱讀 1893·2019-08-30 13:46
閱讀 1574·2019-08-29 15:43