一、使用傳統pymysql執行與sqlite區別
①使用pymysql執行原生sql語句來操作數據
1.sql語句比較復雜,且不好管理
2.sql語句安全性無法保持
3.數據庫創建、數據表生成、數據添加以及數據遷移等非常麻煩
4.sql語句性能不夠好
②使用ORM框架創建數據庫
mysql中的對象
1.數據庫
需要手動創建數據庫
2.數據表
a.與ORM中的模型類一一對應
b.在子應用的models.py中定義模型類
3.字段
a.與模型類的類屬性一一對應
4.記錄
a.與模型類對象一一對應
二、在django中創建數據庫
1、settings.py中
# Database # https://docs.djangoproject.com/en/3.1/ref/settings/#databases # 指定數據庫的配置信息
DATABASES = { # 使用的默認數據庫信息
'default': { 'ENGINE': 'django.db.backends.sqlite3', # a.指定使用的數據庫引擎(使用哪種類型數據庫?)
# 'ENGINE': 'django.db.backends.mysql',
# b.指定數據庫名稱
'NAME': BASE_DIR / 'db.sqlite3', # 'NAME': 'my_django',
# c.指定數據庫的用戶名
# 'USER': 'root',
# d.指定數據庫的密碼
# 'PASSWORD': '123456',
# e.指定數據庫主機地址
# 'HOST': 'localhost',
# f.指定數據庫的端口號
# 'PORT': 3306
} }
2. models.py中
a.定義模型類必須繼承Model或者Model子類,一個模型類相當於一個table
b.定義的類屬性(Field對象)為表中的字段信息
c.默認表名為子應用名_模型類名小寫
d.默認會自動創建一個id主鍵(自增、非空)
e.生成遷移腳本:python manage.py makemigrations 子應用名
f.生成的遷移腳本會自動放置到子應用的migrations目錄中
g.執行遷移腳本:python manage.py migrate 子應用名
from django.db import models # Create your models here. class People(models.Model): name = models.CharField(max_length=20) age = models.IntegerField()
生成遷移腳本:python manage.py makemigrations 子應用名,生成migrations文件夾,里面是遷移腳本
執行遷移腳本:python manage.py migrate 子應用名
執行后可看到生成的DB,如果沒有sqlite驅動,按提示下載
from django.db import models class People(models.Model): """ a.定義模型類必須繼承Model或者Model子類,一個模型類相當於一個table b.定義的類屬性(Field對象)為表中的字段信息 c.默認表名為子應用名_模型類名小寫 d.默認會自動創建一個id主鍵(自增、非空) e.生成遷移腳本:python manage.py makemigrations 子應用名 f.生成的遷移腳本會自動放置到子應用的migrations目錄中 g.執行遷移腳本:python manage.py migrate 子應用名 """ name1 = models.CharField(max_length=20) age = models.IntegerField() class Projects(models.Model): # 一個數據庫模型類中只允許定義一個設置了primary_key=True的字段 # 一旦某個字段設置了primary_key=True,那么ORM框架就不會自動創建id主鍵 # num = models.IntegerField(primary_key=True) id = models.AutoField(primary_key=True, verbose_name='id主鍵', help_text='id主鍵') # a.CharField指定varchar類型 # b.CharField必須得設置max_length參數,指定最大長度 # c.verbose_name與help_text指定中文的描述,在admin后台站點以及在接口文檔平台中會使用到 # d.unique=True設置唯一約束,默認unique=False name = models.CharField(verbose_name='項目名稱', help_text='項目名稱', max_length=20, unique=True) leader = models.CharField(verbose_name='項目負責人', help_text='項目負責人', max_length=10) # e.default指定當前字段的默認值 is_execute = models.BooleanField(verbose_name='是否開展', help_text='是否開展', default=True) # f.null指定當前字段是否允許保持null空值 # g.blank指定前端在創建數據時是否允許不輸入 desc = models.TextField(verbose_name='項目描述信息', help_text='項目描述信息', null=True, blank=True, default='') # DateTimeField指定日期時間類型 # a.auto_now_add=True,在創建一條數據時,會自動將當前時間賦值給create_time,只修改一次 # b.auto_now=True,每次在更新數據時,會自動將當前時間賦值給update_time,只要修改就會自動更新 create_time = models.DateTimeField(auto_now_add=True, verbose_name='創建時間', help_text='創建時間') update_time = models.DateTimeField(auto_now=True, verbose_name='更新時間', help_text='更新時間') class Meta: # a.可以在Meta內部類中修改當前表的元數據信息 # b.指定創建的數據表名稱 db_table = 'tb_projects' # c.指定創建的數據表中文描述信息 verbose_name = '項目表' verbose_name_plural = '項目表' def __str__(self): return self.name
from django.db import models # 表與表之間有哪些關聯關系? # Projects與Interfaces表,一對多的關系 # 學生表與學生詳細信息表,一對一的關系 # 學生表與課程表,多對多的關系 # 一條項目數據:id為1的測試開發平台項目 # 多條接口數據:id為1的登錄接口、id為2的注冊接口、id為3的生成用例的接口 class Interfaces(models.Model): id = models.AutoField(primary_key=True, verbose_name='id主鍵', help_text='id主鍵') name = models.CharField(verbose_name='接口名稱', help_text='接口名稱', max_length=15, unique=True) tester = models.CharField(verbose_name='測試人員', help_text='測試人員', max_length=10) # a.可以使用ForeignKey在從表中指定外鍵字段,在一對多關系中‘多’的那側添加外鍵字段 # b.ForeignKey第一個參數,需要指定關聯的父表,往往使用'子應用名.父表模型類名' # c.必須指定on_delete級聯刪除策略 # d.級聯刪除策略有如下種類: # CASCADE:當父表數據刪除之后,對應的從表數據會被自動刪除 # SET_NULL:當父表數據刪除之后,對應的從表數據的外鍵字段會被自動設置為null # PROTECT:當父表數據刪除時,如果存在對應的從表數據,那么會拋出異常 # SET_DEFAULT:父表數據刪除之后,對應的從表數據的外鍵字段會被自動設置為default參數指定的值 # 創建創建數據表時,會自動創建projects_id作為字段名,用於存放父表外鍵值 # ForeignKey: 一對多 # OneToOneField:一對一 # ManyToManyField:多對多 projects = models.ForeignKey('projects.Projects', on_delete=models.CASCADE) create_time = models.DateTimeField(auto_now_add=True, verbose_name='創建時間', help_text='創建時間') update_time = models.DateTimeField(auto_now=True, verbose_name='更新時間', help_text='更新時間') class Meta: db_table = 'tb_interfaces' verbose_name = '接口表' verbose_name_plural = '接口表' def __str__(self): return self.name
添加數據
一、創建(C)
方式一:
a.直接使用模型類來創建模型對象
b.必須調用save()方法才會執行sql語句(提交)
one_project = Projects(name='XXX金融項目11', leader='大腦斧', desc='這是一個描述')
one_project.save()
方式二:
a.可以使用模型類.objects為manager對象
b.可以使用manager對象.create方法(關鍵字參數)
c.無需調用save方法,會自動提交
one_project = Projects.objects.create(name='XXX在線商城項目11', leader='開始', desc='xxx描述')
添加子表數據
Interfaces(name='登錄接口', tester='Aaron', projects_id=one_project.id)
one_interface = Interfaces(name='登錄接口', tester='Aaron', projects=one_project)
one_interface = Interfaces.objects.create(name='登錄接口', tester='Aaron', projects=one_project)
二、更新數據(U)
方式一:
a.所有的模型類,會有一個默認的objects屬性,是一個manager對象
b.獲取需要修改的模型類對象之后,重寫相應的字段
c.必須得調用save()方法,才會提交
one_project = Projects.objects.get(id=5)
one_project.name = 'XXX在線商城項目22'
one_project.save()
方式二:
a.先將待修改的數據取出(查詢集對象)
b.然后調用update()方法
c.無需調用save()方法,會自動提交
qs = Projects.objects.filter(id=5).update(leader='唯一')
三、查詢(R)
1.讀取多條數據
a.使用模型類.objects.all()
b.返回QuerySet對象,類似於列表,但不是列表
c.QuerySet對象,惰性查找,只有需要用到數據(len、取值、for)時,才會執行sql語句
d.QuerySet對象中為模型類對象(數據)
project_qs = Projects.objects.all()
for pro in project_qs:
print(pro.name)
print(list(project_qs))
2.讀取一條數據
方式一:
a.可以使用模型類.objects.get()
b.如果查詢的結果為空,那么會拋出異常
c.如果查詢的結果超過一條數據,也會拋出異常
d.get方法,往往會使用主鍵或者唯一鍵作為查詢條件
e.返回模型類對象(數據)
one_project = Projects.objects.get(id=1)
pk為django模型類內置的一個屬性,是主鍵的別名
one_project = Projects.objects.get(pk=1)
one_project = Projects.objects.get(Projects.objects.get(leader='大腦斧'))
方式二:
a.模型類.objects.filter方法
b.返回QuerySet對象
c.如果查詢的結果為空,那么會返回空的QuerySet對象
d.如果查詢的結果超過一條,也會返回多條結果所在的QuerySet對象
e.字段名__查詢類型=具體值
f.查詢類型種類?
gt >
gte >=
lt <
lte <=
in 對處於列表中的值進行過濾
contains 包含
icontains 包含,忽略大小寫
startswith 以xxx開頭
istartswith 以xxx開頭,忽略大小寫
endswith 以xxx結尾
iendswith 以xxx結尾,忽略大小寫
isnull 是否為空
qs = Projects.objects.filter(id=4)
qs = Projects.objects.filter(pk=4)
qs = Projects.objects.filter(id__exact=4)
qs = Projects.objects.filter(id__in=[1, 3])
qs = Projects.objects.filter(name__contains='金融')
qs = Projects.objects.filter(update_time__gt='2021-01-18')
exclude與filter為反向關系
qs = Projects.objects.filter(id__gt=3)
qs = Projects.objects.exclude(id__lte=3)
取出某個項目所屬接口名稱中包含'登錄'的項目
關聯查詢
關聯模型類名小寫__關聯模型類中的字段名__查詢類型=具體值
關聯模型類名1小寫__關聯模型類1中的外鍵名__關系模型類2中的字段名__查詢類型=具體值
qs = Projects.objects.filter(interfaces__name__contains='登錄')
qs = Interfaces.objects.filter(name__contains='登錄')
使用外鍵字段,可以取出父表中對應的模型類對象
one_project = qs[0].projects
return HttpResponse(one_project)
QuerySet查詢集的特性
1、惰性查詢
2、鏈式調用
a.查詢集對象可以多次調用filter方法,進行過濾
b.多個filter中的過濾條件為與的關系
c.在一個filter方法中,可以寫多個條件,每個條件之間以“逗號”分割,每個條件為與的關系
3、哪些操作會讓查詢集執行sql語句? 查詢集支持哪些操作?
a.通過數字索引取值,但不支持負值索引
b.支持切片操作
c.支持.first()方法,可以取出查詢集中的第一個元素,為模型類對象
d.支持.last()方法,可以取出查詢集中的最后一個元素,為模型類對象
e.支持len(查詢集對象),獲取查詢集的長度,也可以使用.count()方法
f.支持.exists()方法,來判斷查詢集中是否有元素,如果有元素,那么返回True,否則返回False
g.支持for循環迭代
qs = Projects.objects.filter(name__contains='商城')
邏輯關系
a.與的關系
one = qs.filter(leader='唯一')
qs = Projects.objects.filter(name__contains='商城').filter(leader='唯一')
qs = Projects.objects.filter(name__contains='商城', leader='唯一')
b.或的關系
可以使用Q對象來實現邏輯關系查詢
多個Q對象之間使用|,為或的關系
多個Q對象之間使用&,為與的關系
qs = Projects.objects.filter(Q(name__contains='商城') | Q(leader='大腦斧'))
排序操作
a.默認是以id主鍵升序來排序的
b.查詢集對象.order_by('字段名1','字段名2')
c.默認指定的字段名為升序
d.可以在字段名的前面添加-,代表以降序來排序
刪除操作(D)
方式一:
調用模型類對象中的delete()方法
one_project = Projects.objects.get(pk=1)
one_project.delete()
方式二:
使用查詢集對象.delete(),可以將查詢集中的所有數據刪除
one = Projects.objects.filter(name__contains='商城').delete()
names = ['登錄接口', '注冊接口', '訂單接口', '購物車接口']
for i in range(20):
random_str = ''.join(random.sample(string.ascii_letters + string.digits, 8))
interface_name = random.choice(names) + random_str
Interfaces.objects.create(name=interface_name, tester='Aaron', projects_id=random.choice([2, 3, 4, 5]))
a.values和annotate為固定用法
b.聚合運算需要設置為從表名小寫
c.使用外鍵id作為關聯條件,同時會把外鍵id作為分組條件
d.默認查詢id和聚合運算的值
e.聚合運算的別名會自動設置為從表名小寫__聚合函數名小寫
f.可以給聚合運算設置關鍵詞參數,會作為聚合運算的別名
qs = Projects.objects.values('id').annotate(Count('interfaces'))
qs = Projects.objects.values('id').annotate(interfaces=Count('interfaces'))
qs = Projects.objects.annotate(interfaces=Count('interfaces'))
return HttpResponse('')