模型models
一. 配置数据库
(1) 修改工程目录下的__init__.py
, 添加
import pymysql
pymysql.install_as_MySQLdb()
(2) 修改settings.py
文件, 修改为
DATABASES = {
'default': {
# 'ENGINE': 'django.db.backends.sqlite3',
# 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
'ENGINE': 'django.db.backends.mysql',
'NAME': 'day36', # 数据库名
'USER': 'fanzone',
'PASSWORD': '123',
'HOST': 'localhost',
'PORT': '3306',
}
}
二. 开发流程
1. 配置数据库
2. 创建app
3. 创建模型类
4. 生成迁移文件
5. 创建表结构
6. 对model的增删改查
7. 找到views.py文件写入控制器(视图函数)
8. 配置路由 urls.py在工程目录下
9. 创建模板文件夹
10. 在settings.py配置模板路径
11. 在控制器里使用render()方法 访问模板
三. ORM 对象关系映射
概述: 对象-映射
任务:
- 根据对象的类型生成表结构
- 将对象列表的操作, 转换为SQL语句
- 将SQL语句查询到的结果转换为对象和列表
四. 定义模型
(1) 模型-属性-表-字段之间的关系
一个模型类对应数据库中的一个表, 在模型类中定义的属性对应表中的字段名称
(2) 定义字段属性
(3) 创建模型类
在models.py文件中创建类
(4) 元选项
在模型类中定义一个Meta类, 用于设置元信息
db_table: 自定义设置表名 推荐使用小写字母, 数据表名, 默认为 app名称_类名小写
ordering: 查询数据时, 按照某个字段升序或降序查询, 默认升序
实例:
# 学生表
class Students(models.Model):
pass
class Meta:
db_table = 'student' # 设置当前表名
# ordering = ['pk'] # 按照主键升序查询
ordering = ['-pk'] # 按照主键降序查询,前面带有可选的“-”前缀表示倒序
五. 模型成员
类属性
1. objects 管理器
objects是Manager类型的一个对象, 作用是与数据库进行交互
当定义模型类的时候, 若没有指定管理器 django会为你默认创建一个名为objects的管理器
2. 自定义管理器的名称
# 学生表
class Students(models.Model):
stuObj = models.Manager() # 自定义管理器名称,若指定,则objects不会创建
同时把视图中的代码改为
def stuShow(request):
myDict = {}
# myDict['stu'] = Students.objects.all()
myDict['stu'] = Students.stuObj.all() # 新修改的stuObj
3. 自定义管理器Manager类
一个模型可以有多个模型管理类
操作:
重写父类的get_queryset()方法
实例:
class StudentsManager(models.Manager):
def get_queryset(self): # 重写父类的方法
return super(StudentsManager,self).get_queryset().filter(isDelete=True)# 过滤,符合条件的要
#return super(StudentsManager,self).get_queryset().exclude(isDelete=True) # 符合条件的不要
class Students(models.Model): # 学生表
...
stuObj2 = StudentsManager() # 增加了自己过滤的新的manage管理器
六. 创建对象
(1) 目的
向数据库中添加数据, 当创建对象的时候django不会对数据库进行读写的操作, 当调用save()时候才与数据库交互
(2) 实现方法
1. 在模型类中增加一个类方法
__init__()
方法已经在基类models.Model中使用, 在自定义模型中无法使用重写. # ?
实例:
# 学生表
class Students(models.Model):
pass
# 类方法是可以不通过当前对象实例化去调用的,通过当前的类名.类方法([参数])
# cls 代表Students类,类方法第一个参数为cls
@classmethod # 装饰器声明为类方法
def addStudents(cls, sname, ssex, sage, scontented, sgrade):
stu = cls(sname=sname,ssex=ssex,sage=sage,scontented=scontented,sgrade=sgrade)
return stu
在视图中的操作
def addStudents(request):
# stu = Students()
# stu.sname ='李四'
..
# 通过类方法添加
stu = Students.addStudents('赵六', True, 20, '我是赵六', Grades.objects.get(pk=1))
stu.save()
return HttpResponse('添加学生成功')
2. 在自定义管理器中添加一个方法
实例:
class StudentsManager(models.Manager):
def get_queryset(self):
pass
def addStudents(self, sname, ssex, sage, scontented, sgrade):
# stu = Students() # ok
stu = self.model() # 同上 当模型类名称发生改变 不需要更改当前类名称
stu.sname = sname
stu.ssex = ssex
stu.sage = sage
stu.scontented = scontented
stu.sgrade = sgrade
return stu
在视图中使用
def addStudents(request):
# 通过自定义管理器的方法添加
stu = Students.stuObj2.addStudents('赵六11', True, 20, '我是赵六11', Grades.objects.get(pk=1))
stu.save()
return HttpResponse('添加学生成功')
七. 模型的查询
概述:
- 查询集(queryset)表示从数据库获取对象的集合
- 查询集可以有多个过滤器
- 过滤器就是一个函数, 基于所给的参数, 去限制查询集
- 从SQL角度来说, 查询集合select语句是等价, 过滤器就像where条件
(1) all() 返回查询集中的所有数据/对象
实例:
类名.objects.all() # 返回所有的数据,列表的形式返回(queryset查询集)
myDict['stu'] = Students.stuObj.all()[0:2] # 取两条数据 0 1
stu = Students.stuObj.all()[-1] # error 不支持负索引
通过all()和索引取值做分页例子:
# 学生信息分页
def stuPage(request, nowPage):
myDict = {}
myDict['stu'] = Students.stuObj.all()[(int(nowPage)-1)*2:int(nowPage)*2] # 分页,每页显示2条数据
# print(type(nowPage)) # str 接收到的nowPage为字符串类型
return render(request, 'myApp/stuShow.html', myDict)
url配置:
url(r'stuPage/(\d+)/', views.stuPage), # () 子存储取值传递给nowPage
(2) filter() 返回符号条件的数据
得到的是一个集合的对象, 即queryset
一个条件的情况:
filter(键=值)
Students.objects.filter(sname='张三') # 返回包含sname为张三的列表
多个条件的情况:
filter(键=值, 键=值, ...) # 多个条件之间是并且的关系
myDict['stu'] = Students.stuObj.filter(sname='张三', ssex=False) # 返回sname='张三',性别为女的列表
(3) exclude() 过滤掉符合条件的数据
exclude(键=值, 键=值, ...) # 多个条件之间是并且的关系
myDict['stu'] = Students.stuObj.exclude(sname='张三', ssex=False) # 返回除了sname='张三',性别为女的对象的查找集
(4) order_by('字段名') 排序
升序/降序
格式为:
类名.objects.order_by('字段名') # 升序
类名.objects.order_by('-字段名') # 添加- 表示降序
myDict['stu'] = Students.stuObj.filter(ssex=True).order_by('-id') # 查询条件为 性别为True 按照id降序排列
(5) reverse() 对查询查找集进行反转
格式为: order_by().reverse()
实例:
myDict['stu'] = Students.stuObj.all().order_by('-id').reverse() # ok 为查找集进行反转
myDict['stu'] = Students.stuObj.all().reverse() # 不起作用, 必须要和order_by配合使用
(6) values() 返回查找集, 以列表的形式返回多个字典, 字典的键为字段的名称
实例:
myDict['stu'] = Students.stuObj.values() # 返回查找集, 返回所有的字段的字典
myDict['stu'] = Students.stuObj.values('sname','ssex') # 返回sname和ssex字段的查找集, 返回多个字典,字典中的字段名为键
myDict['stu'] = Students.stuObj.filter(sname='张三').values('sname','ssex') # 返回姓名为张三的sname和ssex字段
(7) values_list() 以列表形式 返回包含的多个元组(每个元素是一个元组), 只包含值, 不包含字段
实例:
# 返回查找集,以列表形式 返回包含的多个元组
myDict['stu'] = Students.stuObj.filter(sname='张三').values_list('sname','ssex') # 返回姓名为张三的sname和ssex字段
八. 返回单个数据
(1) get() 返回一条数据(一个对象)
实例:
stu = Students.stuObj.get() # error 多条数据
stu = Students.stuObj.get(pk=20) # error 没有找到符号条件
stu = Students.stuObj.get(pk=1) # ok Students object 返回对象
# 下面这俩中结果一样
Students.stuObj.filter(sname='李四')[0] <==> Students.stuObj.get(pk=1) # 为对象
注意:
- 如果没有找到符合条件的对象, 会引发模型类的
models.DoesNotExist
异常错误 - 如果查询的数据超过一条, 会引发模型类的
models.MultipleObjectsReturned
异常
(2) count() 统计查询结果集中的对象的个数
格式:
类名.objects.all().count() # 统计所有数据的条数
实例:
Students.objects.all().count() # 统计所有数据的条数
Students.objects.filter(ssex=True).count() # 统计ssex为男的个数
(3) first()/last() 返回查询结果的第一个/最后一个对象
实例:
Students.objects.filter(ssex=True).first() # 第一个对象, filter返回列表,返回列表中的第一个对象
stu = Students.stuObj.filter(ssex=True).first().sname # 张三 返回性别为男的第一个对象的name
Students.objects.filter(ssex=True).last() # 最后一个对象
(4) exists() 判断queryset是否包含数据 如果包含返回True, 否则为False
实例:
Students.objects.filter(ssex=True).exists() # True
Students.objects.filter(pk=20).exists() # False
(5) 字段值的修改
save() : 更适合单条数据的修改
update() : 适用于多条数据
zs = Students.stuObj.get(sname='张三')
zs.sname = '张三三'
zs.save() # 适用于单条数据的修改
Students.stuObj.get(sname='张三三').update(sname='张三') # error update为queryset的查询集的方法
Students.stuObj.filter(sname='张三三').update(sname='张三') # ok
Students.stuObj.all().update(isDelete=False) # ok
Students.stuObj.all().update(isDelete=False, ssex=False) # 修改多个字段,
九. QuerySet 字段比较运算符
(1) 完全匹配运算符
- __exact:大小写敏感
- __iexact:忽略大小写
实例:
Students.stuObj.filter(sname__exact='ab') # 三个结果相同
Students.stuObj.filter(sname='ab') # 同上
Students.stuObj.filter(sname__iexact='ab') # 同上
(2) 是否包含
- __contains: 大小写敏感
- __icontains:忽略大小写
实例:
Students.stuObj.filter(sname__contains='A') # ok AB
Students.stuObj.filter(sname__icontains='A') # 忽略大小写 aB AB
(3) 以..开头/以..结尾
- __startswith:大小写敏感
- __istartswith:忽略大小写
- __endswith:大小写敏感
- __iendswith:忽略大小写
实例:
myDict['stu'] = Students.stuObj.filter(sname__startswith='A') # AB 以A开头
myDict['stu'] = Students.stuObj.filter(sname__startswith='a')
myDict['stu'] = Students.stuObj.filter(sname__istartswith='A') # AB ab 忽略大小写
myDict['stu'] = Students.stuObj.filter(sname__endswith='三') # 以 '三' 结尾
(4) 是否为空
- __isnull:判断为空
值为: True和False
实例:
Students.stuObj.filter(sname__isnull = False) # 查找sname不为空
Students.stuObj.filter(sname__isnull = True) # 查找snmae为空
(5) 在..范围里
- __in:
实例:
Students.stuObj.filter(pk__in = [1,2,3,10]) # id在1,2,3,10中的
Students.stuObj.exclude(pk__in = [1,2,3,10]) # id不在1,2,3,10中的
(6) 在..范围内 相当于between..and
- __range
实例:
Students.stuObj.filter(pk__range = [1,3]) # id为 1-3 范围内的,包括3
(7) 比较
- __gt:大于
- __gte:大于等于
- __lt:小于
- __lte:小于等于
实例:
myDict['stu'] = Students.stuObj.filter(id__gt=3) # id大于3的
myDict['stu'] = Students.stuObj.filter(id__gte=3) # id大于等于3的
myDict['stu'] = Students.stuObj.filter(id__lt=3) # id小于3的
myDict['stu'] = Students.stuObj.filter(id__lte=3) # id小于等于3的
(8) 时间
- __year
- __month
- __day
- __week
- __hour
- __minute
- __second
实例:
Students.stuobj.filter(lasttime__year=2018) # 返回符合条件的对象列表, 最后修改时间的年份为2018的
(9) 聚合函数
- Avg() # 返回所给字段的平均值, 返回类型: float
- Count() # 根据所给的关联字段返回被关联 model 的数量
- Max() # 返回所给字段的最大值
- Min() # 返回所给字段的最小值
- Sum() # 计算所给字段值的总和
导入模块
from django.db.models import Max,Min
配合函数aggregate() 函数去使用
实例:
Students.objects.aggregate(Max('sage')) # 查询年龄最大的值
(10) F对象
概念: 可以使用模型的A属性与B属性比较
导入: from django.db.models import F, Q
实例:
# f对象的控制器
def f(request):
fg = Grades.objects.filter(ggirlnum__gt=F('gboynum')) # 返回girl数量大于boy数量的集合
print(fg[0].gname)
return HttpResponse(fg)
(11) Q对象
概述: 进行条件的或运算
可以组合使用 &(and), |(or), ~(not)操作符, 当一个操作符是用于两个Q的对象, 它产生一个新的Q对象。
导入: from django.db.models import F, Q
实例:
s = Students.stuObj.filter(id__gt=3) # id大于3
s = Students.stuObj.filter(Q(id__gt=3)|Q(id__lt=3)) # 查询id大于3或id小于3的queryset,不包含3
# select * from 表名 where id > 3 or id <3;
s = Students.stuObj.filter(Q(sname='张三'), Q(id__gt=3)|Q(id__lt=3)) # 查询id大于3或id小于3的queryset,不包含3 -------------> filter的逗号进行并操作,可用|进行或操作
# select * from 表名 where sname = and (id >3 or id <3)
for i in s:
print(i.sname)
return HttpResponse('Q对象')
(12) 删除
.delete() # 在数据库中删除数据
实例:
Students.objects.filter(pk_gt=1).delete() # 把主键大于1的数据在数据库中删除
注意:
id/pk/exact, 三种写法结果一样
Students.objects.filter(id=1)
Students.objects.filter(pk=1)
Students.objects.filter(id_exact=1)
网友评论