M — model 数据模型层
作用:方便的操作数据库
一、连接数据库
mysql, sqlserver, oracle…
0.django默认只能连接关系型数据库
1.安装依赖的库
可以使用的库: (1)pymysql (2)python_mysql(不稳定) (3)mysqlclient(配置麻烦)
安装pymsql: pip install pymysql
如果出现 timeout 超时可以使用其他的资源下载:
pip install 模块名 -i https://pypi.douban.com/simple
2. 导入库
在 __init__
文件中编写:
# 导入pymysql模块
import pymysql
pymysql.install_as_MySQLdb()
3.在setting的database中配置mysql的连接
'ENGINE': 'django.db.backends.mysql', # 设置驱动
'NAME':"week01", # 设置数据库名
'USER':'root', # 设置用户名
'PASSWORD':'123', # 设置密码
'HOST':'localhost', # 设置主机地址
'PORT':3306, # 设置端口号
4.注意:不要忘记了在数据库中创建该库
create database 数据库名 charset='utf8';
5.连接mysql数据库
(1)点击右侧database
(2)选择data source,选择数据库类型(如:mysql)
(3)设置账号, 密码, 主机 (注意: 如果对mysql设置远程连接, 需要使用远程连接的账号密码)
(4)测试,点击test connect,出现successful即可
6.测试程序能否能连
(1)执行迁移
python manage.py makemigrations
python manage.py migrate
(2)看到自动生成的表即可
二、orm 对象关系隐射
思想: 相当于一个翻译机
object relational mapping
1.开发人员不要写复杂的sql语句,直接调用对应的方法即可
2.开发人员不需要封装查询结果,查询结果直接就是对象,可以直接使用
3.如果开发人员需要跟换数据库, 不需要更改任何的代码,直接修改数据库的连接即可
三、创建一个表
1.需要在model模块中创建一个类,注意该类必须继承 models.Model
注意: 表名默认是 应用名_类名
2.定义属性名 — 属性需要与表中字段对应
字段名即属性名
字段的数据类型
字段的约束类型
详细:见定义属性
3. 案例:
# 定义模型
# 注意: 执行迁移后,才会在数据库自动创建对应的表
# 默认的表名为: 应用名_类名 类名会自动转换成全小写
# 可以使用(内部类):
class Meta:
db_table = "表名" # 修改表名
# 默认的字段名 就是 定义的属性名, 可以使用 db_column = "字段名" 来修改字段名
# 默认会自动创建主键id,如果使用AutoField则不会自动创建
class Person(models.Model):
p_name = models.CharField(max_length=20,null=False,unique=True)
p_age = models.IntegerField(default=10)
p_sex = models.BooleanField(default=True)
# ....
# 表的结构是可以修改的,修改后,需要重新的迁移才能生效,最好不要修改
# 注: 会自动的检测那些属性进行了修改
四、增加一个数据
1.创建一个对象
2.设置属性
3.保存数据
对象名.save()
五、删除数据
MySQL中删除数据的命令:delete from 表名 whree 条件
0.要删除数据,前提条件是先查询到对应的数据
1.删除:
# 可以直接删除多个结果,也可以直接删除一个
查询结果.delete()
六、修改数据
MySQL中修改数据的命令:update 表名 set 字段名=数据,... where 条件
0.要修改数据,前提条件也是先查询到对应的数据
1.修改
对象名.属性名 = 值
对象名.save()
七、查询数据
1.查询方法
格式: 类名.objects.方法
— 支持链式调用
(1)查询多条结果
all()
获取所有的结果
filter(条件)
按照条件筛选数据
exclude(条件)
筛选出满足条件以外的数据
(2)查询单个结果
first()
获取结果集的第一个
last()
获取结果集的最后一个
get()
获取一个结果, 注意: 有且只有一个结果的时候使用get()
才可以, 如果结果超过一个或者没有, 程序都出错
(3)其他
count()
获取结果集的数量
order_by("-属性名")
表示按照属性名对应的值排序, 默认是升序, -属性名
表示降序排序。如果是字符类型的数据, 是按照字符对应的码表来排序的, 一个字符一个字符的的比较, 如: “aac” "abc"比较 , 则"aac"小,
exists()
判断查询结果集中是否有数据
values()
获取结果集的数据,该数据是类似字典的形式,方便操作
2.条件中的运算符
格式: 属性名__运算符=值
注意:是2个下划线
运算符:
gt 大于
gte 大于等于
lt 小于
lte 小于等于
= 等于 或者 exact
不等于 exclude(条件)
isNull 为空的数据
startwith 查询以某个字符开始
endwith 查询以某个字符结尾的
contain 查询包含某个字符的
istartwith i 是ignore的简写, 忽略大小写查询
iendwith
icontain
in 成员运算符, 是否是集合中值的其中一个,满足一个就符合条件
特殊用法** pk=值 pk是主健的简写
3.Q与F对象
(1)Q对象, 用来帮助实现 逻辑运算符
& 且 如: ...filter(Q(p_age__gt=90) & Q(p_age__lt=95)) # 注意导包
| 或 如: ...filter(Q(p_name="三胖胖40") | Q(p_name="三胖胖61"))
~ 非 如: ...filter(~Q(p_age__lte=100))
(2)F 对象, 用来帮助自己的属性与自己的属性比较
如:
# 需求:实现年龄比id小的数据
persons = Person.objects.filter(p_age__lt=F("id"))
4.查询结果的切片
格式: 结果集[start:stop]
包前不包后 截取从start位置到stop位置的数据
5.聚合函数的使用
Max
Min
Avg
Sum
注意: (1)大小写 (2)注意导包
如:
# 求年龄最大的
res = Person.objects.all().aggregate(Max("p_age"))
# 求年龄最大的
res = Person.objects.all().aggregate(Min("p_age"))