此文章仅作为学习记录
小白学python以此记录为后期复习使用。
欢迎各位大佬来指点文中出现错误的地方。
小白学python交流群(自己创建,无任何商业活动):912477250
持续更新中…
各位朋友,对你有帮助的话,请点个赞呗。谢谢~
Django 框架
1. Django对各种数据库提供了很好的支持,Django为这些数据库提供了统一的调用API,可以根据不同的业务需求选择不同的数据库。
2. 配置数据库
2.1. 修改项目工程目录下的__init__.py
import pymsl
pymsql.instrall_as_MSQLdb()
2.2. 修改setting.py文件中的DATABASES
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'yaoyaomingming', # 数据库名
'USER': 'root', # 数据库用户
'PASSWORD': '123456', # 数据库密码
'HOST': 'localhost', # 数据库IP地址
'PROT': '3306' # 数据库端口号,默认3306
}
}
3. 开发流程
- 创建项目工程目录:执行:
python-admin startproject project
project是项目工程目录名 - 创建项目应用:执行:
python manage.py startapp myApp
myApp是项目应用名 - 激活项目应用
修改:setting.py中的INSTALLED_APPSINSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'myApp' # 激活myApp应用 ]
3.1. 配置数据库(mysql)
-
在
setting.py
文件中,通过DATABASES
选项进行数据库配置。 -
python3.x 安装的是PyMySql
- 修改__init__.py文件导入pymysql引用
# 配置mysql数据库 import pymysql pymysql.install_as_MySQLdb()
- 修改setting.py文件中的DATABASE
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'sunck', # 数据库名 'USER': 'root', # 数据库用户 'PASSWORD': '123456', # 数据库密码 'HOST': 'localhost', # ip地址 'PORT': '3306' # mysql默认端口3306 } }
3.2. 定义模型类
一个模型类都在数据库中对应一张数据表
3.3. 生成迁移文件
-
在项目文件加project下执行
python manage.py makemigrations
出现此处报错:TypeError: ForeignKey.init() missing 1 required positional argument: ‘on_delete’
解决方法:
django升级到2.0之后,表与表之间关联的时候必须写"on_delete"参数,否则会报错
扩展补充说明
参数 | 说明 |
---|---|
on_delete = None | 删除关联表的数据时,当前表与关联表的filed的行为。 |
on_delete = models.CASCADE | 表示级联删除,当关联表(子表)中的数据删除时,与其相对应的外键(父表)中的数据也删除。 |
on_delete = models.DO_NOTHING | 你删你的,父亲(外键)不想管你 |
on_delete = models.PROTECT | 保护模式,如采用这个方法,在删除关联数据时会抛出ProtectError错误 |
on_delete = models.SET_DEFAULT | 设置默认值,删除子表字段时,外键字段设置为默认值,所以定义外键的时候注意加上一个默认值。 |
on_delete = models.SET(值) | 删除关联数据时,自定义一个值,该值只能是对应指定的实体 |
on_delete = models.SET_NULL | 置空模式,删除时,外键字段被设置为空,前提就是blank=True, null=True,定义该字段时,允许为空。理解:删除关联数据(子表),与之关联的值设置默认值为null(父表中),这个前提需要父表中的字段可以为空。 |
执行后会新建一个文件:
在migrations目录下生成一个迁移文件,此时数据库中还没有生成数据库表。
3.4. 执行迁移生成数据表
- 在项目文件加project下执行
python manage.py migrate
- 执行后,会在数据库中创建数据表:
- 相当于执行sql语句,创建了数据表。
3.5. 使用模型类进行增删改查操作
3.6. 启动服务器
- 格式:
python manage.py runserver ip:port
- ip : 可以不写。代表本机ip
- port:默认8000
- 本机测试:
python manage.py runserver
- 说明:这是一个纯python写的轻量级wbe服务器。仅仅在开发测试中使用。
4. ORM
4.1. 概念
4.1.1. 对象-关系-映射
4.2. 任务
- 根据对象的类型生成表结构
- 将对象、列表的操作转换为SQL语句
- 将SQL语句查询到的结果转换为对象、列表
4.3. 优点
- 极大的减轻了开发人员的工作量,不需要面对因数据库的变更二修改代码。
4.4. 图解
5. 定义模型
5.1. 模型、属性、表、字段间的关系
- 一个模型类在数据库中对应一张表。 在模型类中定义的属性,对应该模型对照表中的一个字段。
5.2. 定义属性
5.2.1. 概述
5.2.1.1. django根据属性的类型确定以下信息
- 当前选择的数据库支持字段的类型
- 渲染管理表单时使用的默认html控件
- 在管理站点最低限度的验证
5.2.1.2. django会为表增加自动增长的主键列,每个模型只能有一个主键列。如果使用选项设置某属性为主键列后,则django不会在生成默认的主键列。
5.2.1.3. 属性命名限制
- 遵循标识符规则
- 不能时python的保留关键字
- 由于django的查询方法,不允许使用连续的下划线。
5.2.2. 库
5.2.2.1. 定义属性时,需要字段类型。字段类型被定义在django.db.models.fields目录下,为了方便使用,被导入到django.db.models中。
5.2.2.2. 使用方式
- 导入from django.db import models
- 通过models.Field创建字段类型的对象。赋值给属性。
5.2.3. 逻辑删除
- 对于重要数据都做逻辑删除,不做物理删除。 实现方法时定义isDelete属性,类型BooleanField。默认值为False
5.2.4. 字段类型
5.2.4.1. AutoField
- 一个根据实际ID自动增长的IntegerField,通常不指定。如果不指定,一个主键字段将自动增加到模型中。
5.2.4.2. CharField(max_length=字符串长度)
- 字符串,默认的表单样式是 TextInput
5.2.4.3. TextField
- 大文本字段,一般超过4000使用,默认的表单控件是Textarea
5.2.4.4. IntegerField
- 整数
5.2.4.5. DecimalField(max_digits=None, decimal_places=None)
- 使用python的Decimal实例表示的十进制浮点数
- DecimalField.max_digits 位数总数
- DecimalField.decimal_places 小数点后的数字位数
简单示例:
3.1415926
max_digits = 8
decimal_places=7
5.2.4.6. FloatField
- 用python的float实列来表示浮点数
5.2.4.7. BooleanField
-True/False 字段。 此字段的默认表单控制是CheckboxInput。布尔值。
5.2.4.8. NullBooleanField
- 支持null、true、false 三种值
5.2.4.9. DateField([auto_now=False, auto_now_add=False])
- 使用Python的datetime.date实例表示的日期(yyyy-mm-dd)
参数说明
- DateField.auto_now
设置为True时,每次保存对象时,自动设置该字段为当前时间,用于最后一次修改的时间戳,它总是使用当前日期。默认为False。 - DateField.auto_now_add
设置为True时,当对象第一次被创建时设置当前时间,用于创建的时间戳,它总是使用当前日期。默认为False。
说明: 该字段默认对应的表单控件是一个TextInput。在管理员站点添加了一个JavaScript写的日历控件,和一个“Today”的快捷按钮,包含了一个额外的invalid_date错误消息键。
注意: auto_now_add、auto_now、and default 这些设置是相互排斥的,它们之间的任何组合将会发生错误的结果。
5.2.4.10. TimeField
- 使用Python的datetime.time 实例表示的时间,参数同DateField
5.2.4.11. DateTimeField
- 使用Python的datetime.datetime实例表示日期和时间。参数同DateField
5.2.4.12. FileField
- 一个上传文件的字段
5.2.4.13. ImageField
- 继承了FileField的所有属性和方法。但对上传的对象进行校验,确保它是个有效的image
- 只能上传图片
5.2.5. 字段选项
5.2.5.1. 概述
- 通过字段选项可以实现对字段的约束。 在字段对象是通过关键字参数指定。
5.2.5.2. null
- 如果为True,Django将空值以NULL 存储到数据库中,默认是False
5.2.5.3. blanke
- 如果为True,则该字段允许为哦空,默认值为False
5.2.5.4. db_ column=‘字段名’
- 字段的名称,如果未指定,则使用属性的名称。
5.2.5.5. db_index
- 若值为True,则在表中会为此字段创建索引。
5.2.5.6. default
- 默认值
5.2.5.7. primary_key
- 若为True,则该字段会成为模型的主键字段。
5.2.5.8. unique
- 如果为true,这个字段在表中必须有唯一值。
注意: null是数据库范畴的概念,blank是表单验证范畴的概念。(null, blanke)
5.2.6. 关系
5.2.6.1. 分类
ForeignKey
- 一对多,将字段定义在多的一端。
ManyToManyField
- 多对多,将字段定义在两端中
OneToOneField
- 一对一,将字段定义在任意一端中。
5.2.6.2. 用一访问多
格式
- 对象.模型类小写_set
- 示例
grade = Grades()
grade.students_set # 用一访问多, 访问一个班级有多少个学生。
5.2.6.3. 用一访问一
格式
-
对象.模型类小写
-
示例
grade = Grades()
grade.students # 用于一访问一。 访问内班级中的一位同学
5.2.6.4. 访问一的记录id
格式
-
对象.属性_id
-
示例
studnet = Students()
student.sgrade_id # 访问学生属于那个班级的id
5.3. 创建模型类
5.4. 元选项
5.4.1. 在模型类定义的Meta类,用于设置元信息。
5.4.2. db_table
- 定义数据表名,推荐使用小写字母。数据表明默认为项目应用名小写_类名小写
5.4.3. ordering
5.4.3.1. 对象默认排序字段,获取对象的列表时使用。
5.4.3.2. ordering=[‘id’]:升序
5.4.3.3. ordering=[‘-id’] :降序
- 注意:排序会增加数据库的开销。消耗资源。
# 学生
class Students(models.Model):
snmae = models.CharField(max_length=20)
sgender = models.BooleanField(default=True)
sage = models.IntegerField()
scontend = models.CharField(max_length=20)
isDelete = models.BooleanField(default=False)
# 所属班级 关联外键 # 不加on_delete参数时,生成迁移文件是会报错。
sgrade = models.ForeignKey("Grades", on_delete=models.DO_NOTHING)
lastTime = models.DateTimeField(auto_now=True)
createTime = models.DateTimeField(auto_now_add=True)
# 元选项
class Meta:
db_table = 'students'
ordering = ['id']
6. 模型成员
6.1. 类属性
6.1.1. objects
-
是Manager类型的对象,作用是与数据库进行交互。
-
当定义模型类时没有指定管理器,那么Django为模型创建一个名为objects的管理器。
6.1.2. 自定义管理器
- 示例代码
# 学生
class Students(models.Model):
# 当定自定义模型管理器,objects就不存在了
stuObj = models.Manager()
- 当为模型指定模型管理器,Django就不再为模型类生成objects模型管理器。
6.1.3. 自定义管理器Manager类
- 模型管理器是Django的模型进行与数据库进行交互的接口,一个模型可以有多个模型管理器。
6.1.3.1. 作用
-
向管理器类中添加额外的方法
-
修改管理器返回的原始查询集
-
重写get.queryset()方法
-
代码示例
class StudentsManager(models.Manager):
def get_queryset(self):
# 逻辑删除的不要,只查询没有逻辑删除的。
return super(StudentsManager, self).get_queryset().filter(isDelete=False)
# 学生
class Students(models.Model):
# 自定义模型管理器
# 当定自定义模型管理器,objects就不存在了
stuObj = models.Manager()
stuObj2 = StudentsManager()
6.2. 创建对象
6.2.1. 目的
-
向数据库添加数据
-
当创建对象时,Django不会对数据建库进行读写操作,当调用save()方式时才与数据库交互,将对象保存到数据库中。
-
注意:__init__方法已经在父类models.Model中使用。在自定义的模型中无法使用。
6.2.4. 方法
6.2.4.1. 在模型类中添加一个类方法
# 定义一个类方法创建对象
@classmethod
def createStudents(cls, name, age, gender, contend, grade, last, create, isDel=False):
stu = cls(snmae=name,sage=age,sgender=gender,scontend=contend,sgrade=grade,lastTime=last,createTime=create,isDelete=isDel)
return stu
6.2.4.2. 在定义管理器中添加一个方法
# 学生管理器
class StudentsManager(models.Manager):
def get_queryset(self):
return super(StudentsManager, self).get_queryset().filter(isDelete=False)
# 创建对象,添加数据
def createStudent(self, name, age, gender, contend, grade, last, create, isDel=False):
stu = self.model()
stu.snmae = name
stu.sage = age
stu.sgender = gender
stu.scontend = contend
stu.sgrade = grade
stu.lastTime = last
stu.createTime = create
stu.isDelete = isDel
return stu
6.3. models.py完整代码
from django.db import models
# Create your models here.
# 班级
class Grades(models.Model):
gname = models.CharField(max_length=20)
gdate = models.DateField()
ggirlnum = models.IntegerField()
gboynum = models.IntegerField()
isDelete = models.BooleanField(default=False)
# 元选项
class Meta:
db_table = 'grades'
ordering = ['-id']
# 学生管理器
class StudentsManager(models.Manager):
def get_queryset(self):
return super(StudentsManager, self).get_queryset().filter(isDelete=False)
# 创建对象,添加数据
def createStudent(self, name, age, gender, contend, grade, last, create, isDel=False):
stu = self.model()
stu.snmae = name
stu.sage = age
stu.sgender = gender
stu.scontend = contend
stu.sgrade = grade
stu.lastTime = last
stu.createTime = create
stu.isDelete = isDel
return stu
# 学生
class Students(models.Model):
# 自定义模型管理器
# 当定自定义模型管理器,objects就不存在了
stuObj = models.Manager()
stuObj2 = StudentsManager() #创建管理器用于查询代替objects
snmae = models.CharField(max_length=20)
sgender = models.BooleanField(default=True)
sage = models.IntegerField()
scontend = models.CharField(max_length=20)
isDelete = models.BooleanField(default=False)
# 所属班级 关联外键 # 不加on_delete参数时,生成迁移文件是会报错。
sgrade = models.ForeignKey("Grades", on_delete=models.DO_NOTHING)
lastTime = models.DateTimeField(auto_now=True)
createTime = models.DateTimeField(auto_now_add=True)
def __str__(self):
return f'{self.snmae} -- {self.sage}'
# 元选项
class Meta:
db_table = 'students'
ordering = ['id']
# 定义一个类方法创建对象
@classmethod
def createStudents(cls, name, age, gender, contend, grade, last, create, isDel=False):
stu = cls(snmae=name, sage=age, sgender=gender, scontend=contend,sgrade=grade, lastTime=last, createTime=create, isDelete=isDel)
return stu
6.4. views.py完整代码
from django.shortcuts import render
# Create your views here.
from django.http import HttpResponse
from myApp.models import Students, Grades
def index(request):
return HttpResponse('欢迎来到Django的视图模块...')
def students(request):
studentsList = Students.stuObj2.all()
return render(request, 'myApp/index.html', {'students': studentsList})
def addStudent(request):
grade = Grades.objects.get(pk=1)
stu = Students.createStudents('耀明',34,True,'我叫耀明,请多关照。',grade,'2022-07-23','2022-08-01')
stu.save()
return HttpResponse(f"添加成功!")
def addStudent2(request):
grade = Grades.objects.get(pk=1)
stu = Students.stuObj2.createStudent('杳杳明明',34,True,'我叫杳杳明明,请多关照。',grade,'2022-07-23','2022-08-01')
stu.save()
return HttpResponse(f"添加成功!")
7. 模型查询
7.1. 概述
-
查询集表示从数据库获取的对象集合
-
查询可以有多个过滤器
-
过滤器就是一个函数,基于所给的参数限制查询集结果。
-
从sql角度来书,查询集合select语句等价。过滤器就像where条件语句。
7.2. 查询集
-
在管理器上调用过滤器方法返回查询集
-
查询集经过过滤器帅选后返回新的查询集,所以可以写成链式调用。
-
惰性执行
- 创建查询集不会带来任何数据的访问,直到调用数据时,才会访问数据。
-
直接访问数据的情况
- 迭代
- 序列化
- 与if合用
7.2.5. 返回查询集的方法称为过滤器
7.2.5.1. all()
- 返回查询集中的所有数据
7.2.5.2. filter()
- 保留符合条件的数据
- filter(键=值)
- filter(键=值, 键=值)
- filter(键=值).filter(键=值)
- and 且
7.2.5.3. exclude()
- 过滤掉符合条件的数据
7.2.5.4. order_by()
- 排序
7.2.5.5. values()
- 一条数据就是一个对象(字典),返回一个列表
7.2.6. 返回单个数据
7.2.6.1. get()
-
返回一个满足条件的对象
-
注意
- 如果没有找到符合条件的对象,会引发“模型类.DoesNotExist”异常
- 如果找到多个对象,会引发“模型类.MultipleObjectsReturned”异常
7.2.6.2. count()
- 返回当前查询集中的对象个数
7.2.6.3. first()
- 返回当前查询集中的第一个对象
7.2.6.4. last()
- 返回当前查询集中的最后一个对象
7.2.6.5. exists()
- 判断查询集中是否有数据,有数据返回True,没有数据返回False
7.2.7. 限制查询集
7.2.7.1. 查询集返回列表,可以使用下标的方法进行限制,等同于sql中的limit语句
- 显示前5条数据
# 显示前5条数据 studentsList = Students.stuObj2.all()[0:5]
- 注意:下标不能用负数
7.2.7.4. 分页查询
views.py代码
# 分页显示学生
def stuPage(request, curPage):
# 分页 (curPage-1)*pageSize,pageSize
# curPage 当前页码
# pageSize 每页显示的数量
curPage = int(curPage)
studentsList = Students.stuObj2.all()[(curPage-1)*5:curPage*5] # 显示前5条数据
return render(request, 'myApp/index.html', {'students': studentsList})
myApp目录下urls.py代码
from django.urls import path, include, re_path
from . import views
urlpatterns = [
re_path(r'^$', views.index),
re_path(r'^students/$', views.students),
re_path(r'^addStudent/$', views.addStudent),
re_path(r'^addStudent2/$', views.addStudent2),
re_path(r'^stu/(\d+)/$', views.stuPage), # 分页查询
]
访问效果地址:http://127.0.0.1:8000/stu/2/
7.2.8. 查询集的缓存
7.2.8.1. 概述
-
每个查询集都包含一个缓存,来最小化的对数据库访问。
-
在新建的查询集中,缓存首次为空,第一次对查询集求值,会发生数据缓存。Django会将查询出来的数据做一个缓存,并返回查询结构,以后的查询直接使用查询集的缓存。
7.2.9. 字段查询
7.2.9.1. 概述
-
实现了sql中的where语句,作为方法filter()、exclude()、get()的参数
-
语法
- 属性名称__比较运算符=值
外键
- 属性名称_id
转义
-
like语句中使用%是为了匹配占位,特殊字符。匹配数据中的%(where like ‘%’)
-
filter(snmae__contains=‘%’) # %不用转义
7.2.9.2. 比较运算符
exact
-
说明:判断,大小写敏感
-
示例:filter(isDelete=False)
contains
- 说明:是否包含,大小写敏感
- 示例
# 查找含有张氏的记录 Students.stuObj2.filter(snmae__contains='张氏')
startswith、endswith
-
说明:以value开头或结尾,大小写敏感
-
示例
# 开头以杳杳的记录 studentsList = Students.stuObj2.filter(snmae__startswith='杳杳')
以上四个在前面加上i ,就表示不区分大小写。iexact、icontains、istartswith、iendswith(exact, contains, startswith、endswith)
isnull、isnotnull
-
说明:是否为空
-
示例:filter(snmae__isnull=False)
in
- 说明:是否包含在范围内
- 示例
studentsList = Students.stuObj2.filter(pk__in=[3,4,5,15,17])
gt 大于 gte 大于等于 lt 小于 lte 小于等于
- 年龄大于30岁的学生
# 年龄大于30岁的学生 studentsList = Students.stuObj2.filter(sage__gt=30)
year 年 month 月 day 日 week_day 星期 hour 时 minute 分 second 秒
- 查找lastTime字段日期在2022年的记录
# 查找lastTime字段日期在2022年的记录 studentList = Students.stuObj2.filter(lastTime__year=2022)
跨关联查询
处理join查询
-
语法
- 模型类名_属性名_比较运算符
获取id=1的班级中的所有学生
gradel = Grades.objects.get(pk=1)
gradel.students_set.all()
查询描述(scontend)中带有“杳杳”这两个字的数据是属于哪个班级的学生。
grade = Grades.objects.filter(students__scontend__contains='杳杳')
print(grade[0].gname)
print(type(grade))
创建王五学生,属于pk=1班级。
gradel = Grades.objects.get(pk=1)
stu3 = gradel.students_set.create(snmae=u'王五',sgender=True,scontend=u'我叫王五',sage = 50)
注意:直接添加到数据库中。
查询快捷
pk
代表的主键
7.2.9.3. 聚合函数
使用aggregate()函数返回聚合函数的值
Avg、 Count、 Max、 Min、 Sum
- 以Max示例:
from django.db.models import Max maxAge = Students.stuObj2.aggregate(Max('sage'))
想使用哪个就导入哪个。如MAX(Avg, Count, Max, Min, Sum)
7.2.9.4. F对象
可以使用模型的A属性与B属性进行比较
- 得到班级女生数量(ggirlnum)大于男生数量(gboynum)的班级
from django.db.models import F, Q def grades(request): g = Grades.objects.filter(ggirlnum__gt=F('gboynum')) print(g) return HttpResponse('....')
支持F对象的算数运算
- 得到班级女生数量(ggirlnum)大于(男生数量(gboynum)+20)的班级
from django.db.models import F, Q def grades(request): g = Grades.objects.filter(ggirlnum__gt=F('gboynum')+20) print(g) return HttpResponse('....')
7.2.9.5. Q对象
概述
- 过滤器的方法中的关键字参数,条件为And模式
需求
- 进行or查询
解决
- 使用Q对象
举例
- 找出id小于等于3 或 学生年龄大于等于34的学生
studentsList = Students.stuObj2.filter(Q(pk__lte=3) | Q(sage__gte=34))
只有一个Q对象,就是用来匹配的。
- 查询id小于等于3的学生记录。
studentsList = Students.stuObj2.filter(Q(pk__lte=3))
取反(~)
- 查询id大于3的学生记录
studentsList = Students.stuObj2.filter(~Q(pk__lte=3))