[toc]
1 模型
Django對各種數(shù)據(jù)庫都提供了很好的支持,Django為這些數(shù)據(jù)庫提供了統(tǒng)一的調(diào)用API,可以根據(jù)不同的業(yè)務(wù)需求,選擇不同的數(shù)據(jù)庫;
1.1 開發(fā)流程
配置數(shù)據(jù)庫:
python3.x 安裝的是PyMySQL; python2.x 安裝的是mysql-python
在工程目錄下的__init__.py寫入兩行代碼
import pymysql
pymysql.install_as_MySQLdb()
配置 settings.py
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'class',
'USER': 'root',
'PASSWORD': 'admin',
'HOST': '192.168.23.128',
'PORT': '3306',
}
}
定義模型類
一個模型類都在數(shù)據(jù)庫中隊形一張數(shù)據(jù)表;
生成遷移文件
執(zhí)行遷移
使用模型類進行增、刪、改、查
1.2 ORM
1.2.1 概述
對象-關(guān)系-映射
1.2.2 任務(wù)
- 根據(jù)對象類型生成表結(jié)構(gòu);
- 將對象、列表的操作轉(zhuǎn)換為SQL語句;
- 將SQL語句查詢到的結(jié)果轉(zhuǎn)換為對象、列表;
1.2.3 優(yōu)點
- 極大的減輕了開發(fā)人員的工作量,不需要面對因數(shù)據(jù)庫的改變而修改代碼;
1.2.4 圖解
graph TD
A[Django]
B[ORM]
C1[MySQL]
C2[sqlite]
C3[Oracle]
1.3 定義模型
1.3.1 模型、屬性、表、字段間的關(guān)系
- 一個模型類在數(shù)據(jù)庫中對應(yīng)一張表;
- 在模型類中定義的屬性,對應(yīng)該模型對照表中的一個字段;
1.3.2 定義屬性
1. 概述
- Django根據(jù)屬性的類型確定以下信息:
- 當前選擇的數(shù)據(jù)庫支持字段的類型;
- 渲染管理表單時使用的默認html控件;
- 在管理站點最低限度的驗證;
- Django會為表增加自動增長的主鍵列;
每個模型只能有一個主鍵列;
如果使用選項設(shè)置某屬性為主鍵列后,則Django不會再生成默認的主鍵列;
- 屬性命名限制:
- 遵循標識符規(guī)則
- 不能是python的保留關(guān)鍵字;
- 由于Django的查詢方式,不允許使用連續(xù)的下劃線;
2. 庫
- 定義屬性時,需要字段類型,字段類型被定義在 django.db.models.fields 目錄下;
為了方便使用,被導(dǎo)入到 django.db.models 中;
- 使用方式:
- 導(dǎo)入: from django.db import models
- 通過 models.Field 創(chuàng)建字段類型的對象,賦值給屬性;
3. 邏輯刪除
- 對于重要數(shù)據(jù)都做邏輯刪除,不做物理刪除;
實現(xiàn)方法是定義 isDelete 屬性,類型為 BooleanFiled,默認值為 False;
4. 字段類型
字段類型(字段選項)
AutoField
一個根據(jù)實際 ID 自動增長的 IntegerField,通常不指定;
如果不指定,一個主鍵字段將自動添加到模型中;
CharField(max_length=字符長度)
字符串,默認表單樣式是 TextInput;
TextField
大文本字段,一般超過4000字節(jié)使用,默認表單控件是 Textarea;
IntegerField
整數(shù)類型;
DecimaField(max_digits=None, decimal_places=None)
使用 python 的Decimal 實例表示的十進制浮點數(shù);
參數(shù)說明:
DecimalField.max_digits
位數(shù)總數(shù)
DecimalField.decimal_places
小數(shù)點后的數(shù)字位數(shù)
FloatField
用 python 的 float 實例來表示的浮點數(shù);
BooleanField
True/False 字段,此字段的默認表單控制是 CheckboxInput;
NullBooleanField
支持Null、True、False三種值;
DateField(auto_now=False, auto_now_add=False)
使用 python 的 datetime.date 實例表示日期;
參數(shù)說明:
DateField.auto_now
每次保存對象時,自動設(shè)置該字段為當前時間,用于“最后一次修改”的時間戳,它總是使用當前日期,默認為 False;
DateField.auto_now_add
當對象第一次被創(chuàng)建時自動設(shè)置當前時間,用于創(chuàng)建的時間戳,它總是使用當前日期,默認為 False;
說明:
該字段默認對應(yīng)的表單控件是一個 TextInput;<br>在管理員站點添加了一個 JavaScrtpt 寫的日歷控件,和一個“Today”的快捷按鈕;<br>包含了一個額外的 invalid_date 錯誤消息鍵;
注意:
auto_now、auto_now_add、default 這些設(shè)置是相互排斥的,他們之間的任何組合都將會發(fā)生錯誤的結(jié)果;
TimeField
使用 python 的 datetime.time 實例表示的時間,參數(shù)同 DateField;
DateTimeField
使用 python 的 datetime.datetime 實例表示的日期和時間,參數(shù)同 DateField;
FileField
一個上傳文件的字段;
ImageField
繼承了 FileField 的所有屬性和方法,但對上傳的對象進行校驗,確保它是個有效的 image;
5. 字段選項
字段類型(字段選項)
概述:
通過字段選項,可以實現(xiàn)對字段的約束;
在字段對象時,通過關(guān)鍵字參數(shù)指定;
null
null = True 一般不寫
如果為 True,Django 將空值以 NULL 存儲到數(shù)據(jù)庫中,默認值是 False;
blank
如果為 True,則該字段允許為空白,默認值是 False;
注意:null 是數(shù)據(jù)庫范疇的概念;blank 是表單驗證范疇的概念;
db_column
sage = models.IntegerField(db_column='age') 指定這個字段再數(shù)據(jù)庫中名字是age
字段的名稱,如果未指定,則使用屬性的名稱;
db_index
若值為 True,則在表中會為此字段創(chuàng)建索引;
default
默認值
primary_key
若為True,則該字段會成為模型的主鍵字段;
unique
如果為True,則該字段再表中必須有唯一值;
6. 關(guān)系
分類:
Foreignkey:一對多,將字段定義在多的端中
Grades 和 Students 是一對多關(guān)系,F(xiàn)oreignkey定義在Students中;
ManyToManyField:多對多,將字段定義在兩端中;
OneToOneField:一對一,將字段定義在任意一端中;
用一訪問多:
格式: 對象.模型類小寫_set
示例: grade.student_set
用一訪問一:
格式: 對象.模型類小寫
示例: grade.student
訪問id:
格式: 對象.屬性_id
示例: student.sgrade_id
1.3.3 創(chuàng)建模型類
1.3.4 元選項
在模型類中定義Meta類,用于設(shè)置元信息;
class Grade(models.Molde):
class Meat:
db_table='students' # 定義數(shù)據(jù)表名,推薦使用小寫字母,數(shù)據(jù)表名默認為:項目名小寫_類名小寫
ordering=['id'] # 對象的默認排序字段,獲取對象的列表時使用
ordering=['id] # 按id字段升序排列
ordering=['-id'] # 按id字段降序排列
注意: 排序會增加數(shù)據(jù)庫開銷
示例:
class Student(models.Model):
sname = models.CharField(max_length=20)
sgender = models.BooleanField(default=True)
sage = models.IntegerField()
scontend = models.TextField()
isDelete = models.BooleanField(default=False)
sgrade = models.ForeignKey('Grade')
def __str__(self):
return self.sname
lasttime = models.DateTimeField(auto_now=True)
createtime = models.DateTimeField(auto_now_add=True)
class Meta:
db_table = 'student'
ordering = ['id']
1.4 模型成員
1.4.1 類屬性
objects
是Manager類型的一個對象,作用是與數(shù)據(jù)庫進行交互;
當定義模型類時,沒有指定管理器,那么Django為模型創(chuàng)建一個名為objects的管理器;
自定義管理器:
class Student(models.Model):
# 自定義模型管理器
stuObj = models.Manager()
stu = Student.stuObj.get(pk=1)
當為模型指定模型管理器,Django就不在為模型類生成objects模型管理器;
自定義管理器Manager類:
模型管理器是Django的模型進行與數(shù)據(jù)庫進行交互的接口;一個模型類可以有多個模型管理器;
stuObj = models.Manager()
stuObj1 = models.Manager()
作用:
向管理器類中添加額外的方法
修改管理器返回的原始查詢集 重寫get_queryset()方法
示例: 查詢Student表中 isDelete=Flase的內(nèi)容
class StudentManager(models.Manager):
def get_queryset(self):
return super(StudentManager, self).get_queryset().filter(isDelete=False)
class Student(models.Model):
# 自定義模型管理器
stuObj = models.Manager()
stuObj2 = StudentManager()
1.4.2 創(chuàng)建對象
目的:
項數(shù)據(jù)庫添加數(shù)據(jù)
當創(chuàng)建對象時,Django不會對數(shù)據(jù)庫進行讀寫操作;
當調(diào)用save時,才與數(shù)據(jù)庫有交互,將對象保存到數(shù)據(jù)庫中;
注意:
__init__() 方法已經(jīng)在父類models.Model中使用,在自定義的模型中無法使用;
方法:
1. 在模型類中增加一個類方法;
class Student(models.Model):
# @classmethod 表明是類方法
@classmethod
def createStudents(cls, name, gender, age, contend, isD=False):
stu = cls(sname = name,
sgender = gender,
sage = age,
scontend = contend,
isDelete=isD)
return stu
#-------------------------------------------------------------------------------
# views.py
def addStudent(request):
grade = Grade.objects.get(pk=1)
stu = Student.createStudents("劉德華", True, 34, '我叫劉德華', grade)
stu.save()
return HttpResponse('Yeah')
#-------------------------------------------------------------------------------
# urls.py
url(r'^addstudent/$', views.addStudent),
2. 在自定義管理器中添加一個方法
class StudentManager(models.Manager):
def createStudent(self, name, gender, age, contend, grade, isD=False):
stu = self.model()
stu.sname = name
stu.sgrade = gender
stu.sage = age
stu.scontend = contend
stu.sgrade = grade
return stu
1.4.3 模型查詢
概述:
查詢集表示從數(shù)據(jù)庫獲取的對象的集合;
查詢集可以有多個過濾器;
過濾器就是一個函數(shù),基于所給的參數(shù)限制查詢集結(jié)果;
從SQL角度來說,查詢集和select語句等價,過濾器等同于 SQL 的 where 條件;
查詢集:
在管理器調(diào)用過濾器方法,返回查詢集;
查詢集經(jīng)過過濾器篩選后,返回新的查詢集,所以可以寫成鏈式調(diào)用;
惰性執(zhí)行:
創(chuàng)建查詢集不會帶來任何數(shù)據(jù)庫的訪問,直到調(diào)用數(shù)據(jù)時們才會訪問數(shù)據(jù);
直接訪問數(shù)據(jù)的情況:
迭代
序列化
與if合用
返回查詢集的方法稱為過濾器:
all() 返回查詢集中所有的數(shù)據(jù)的對象;
filter()
返回符合條件的數(shù)據(jù);
filter(鍵=值, 鍵=值)
filter(鍵=值).filter(鍵=值)
exclude() 過濾掉符合條件的數(shù)據(jù)
order_by() 排序
values() 以條數(shù)據(jù)就是一個字典,返回一個列表;
返回單個數(shù)據(jù):
get()
返回一個滿足條件的對象;
注意:
如果沒有找到符合條件的對象,會引發(fā) "模型類.DoesNotExist" 異常;
如果找到多個對象,會引發(fā) "模型類.MultipleObjectsReturned" 異常;
count() 返回當前查詢集中的個數(shù);
first() 返回當前查詢集中的第一個對象;
last() 返回當前查詢集中的最后一個對象;
exists() 判斷查詢集中是否有數(shù)據(jù),有則返回True;
限制查詢集:
查詢集返回列表,可以使用下標來進行限制,等同于 SQL 的 limit 語句;
def student3(request):
studentList = Student.stuObj.all()[0:3]
return render(request, 'myapp/student.html', {'student': studentList})
注意:下標不能是負數(shù);
需求:分頁顯示學生信息
url.py
url(r'^stupage/(\d)/$', views.stupage),
views.py
def stupage(request, page):
# 0-3 3-6 6-9
# 1 2 3
page = int(page)
studentList = Student.stuObj.all()[(page-1)*3: (page*3)]
return render(request, 'myapp/student.html', {'student': studentList})
查詢集的緩存:
概述:
每個查詢集都包含一個緩存,來最小化對數(shù)據(jù)庫訪問;
在新建的查詢集中,緩存首次為空,第一次對查詢集求值,會發(fā)生數(shù)據(jù)緩存;
Django會將查詢的數(shù)據(jù)做一個緩存,并返回查詢結(jié)果,以后查詢直接使用查詢集的緩存;
字段查詢:
概述:
實現(xiàn)了 SQL 中的 where 語句,作為方法filter()、exclude()、get()的參數(shù)
語法:
屬性名稱__比較運算符=值
外鍵:
屬性名_id
轉(zhuǎn)義:
like 語句使用%是為了匹配占位,匹配數(shù)據(jù)中的% (where like '\%')
filter(sanme_cotains='%')
比較運算符:
exact
判斷,大小寫敏感(區(qū)分大小寫)
filter(isDelete=False)
contans
是否包含,大小寫敏感
studentList = Student.stuObj.all().filter(sname__contains='張')
startswith、endswith
以value開頭或者結(jié)尾,大小寫敏感
studentList = Student.stuObj.all().filter(sname__startswith='張')
以上四個在參數(shù)前加 i 就表示不區(qū)分大小寫:iexact、icontans、istartswith、iendswith
isnull、isnotnull
是否為空
in
是否包含在范圍內(nèi)
studentList = Student.stuObj.all().filter(pk__in=[2,4,6,8])
gt 大于
gte 大于等于
lt 小于
lte 小于等于
studentList = Student.stuObj.all().filter(sage__gt=20)
year
month
day
week_day
hour
minute
second
給datetime、date、time類型的字段使用
跨關(guān)聯(lián)查詢
處理join查詢
語法:
模型類名__屬性名__比較運算符
grade = Grade.objects.filter(student__scontend__contains='劉德華')
print(grade)
描述中帶有劉德華的班級的內(nèi)容
查詢快捷
pk 代表主鍵
聚合函數(shù):
使用aggregate()函數(shù)返回聚合函數(shù)的值;
Avg
Count
Max
Min
Sum
from django.db.models import Max
def studentSearch(request):
maxAge = Student.stuObj.aggregate(Max('sage'))
F對象
可以使用模型的 A屬性 與 B屬性 進行比較
from django.db.models import F
def grades(request):
g = Grades.object.filter(ggirlnum__gt=F('gboynum'))
print(g)
return HttpResponse('女生比男生數(shù)多的班')
支持F對象的算數(shù)運算
g = Grades.object.filter(ggirlnum__gt=F('gboynum')+10)
支持F對象的時間的運算
Q對象
概述: 過濾器的方法中的關(guān)鍵字參數(shù),條件為and模式
需求: 進行or查詢
解決: 使用Q對象
studentList = Student.stuObj2.filter(Q(pk__lt=5) | Q(sage__gt=20))
studentList = Student.stuObj2.filter(Q(pk__lt=5)) 只有一個Q對象,就是用于匹配的;
studentList = Student.stuObj2.filter(~Q(pk__lt=5)) ~ 取反
1.4.4 刪、改
刪
對象名.del()
改
對象名.save()