数据库配置和迁移
- Django项目默认
sqlite3
数据库, 生成的数据库名为db.sqlite3
sqlite3
仅供测试使用,可以通过配置修改为使用mysql
一、配置使用MySQL数据库
-
手动创建
MySQL
数据库,比如叫:db_django01
create database db_django01 charset=utf8;
-
在与项目
setting.py
文件中配置使用mysqlDATABASES = { 'default': { # 配置使用mysql 'ENGINE': 'django.db.backends.mysql', # 数据库产品 'HOST': "localhost", # 数据库ip 'PORT': 3306, # 数据库端口 'USER': "root", # 用户名 'PASSWORD': "mysql", # 密码 'NAME': "db_django01", # 数据库名 } }
-
在python虚拟环境下安装 MySQL 驱动
pip install pymysql
-
在
与项目同名的包
下的__init__.py
文件中,初始化MySQL驱动import pymysql pymysql.install_as_MySQLdb()
二、迁移命令生成表
打开终端,进入到项目根目录下,执行以下2个命令,生成数据库表
1. 生成迁移文件
python manage.py makemigrations
2. 生成数据库表
python manage.py migrate
3. 查看数据库表
一、需求
定义模型类,保存部门-员工数据
-
部门类(Department)
- 部门名称: name
- 部门成立时间: create_date
- 逻辑删除标识:is_delete
-
员工类(Employee)
- 姓名: name
- 年龄: age
- 性别: sex
- 工资: salary
- 入职时间: hire_date
- 备注信息: comment
二、模型类定义
- 模型类被定义在
应用/models.py
文件中 - 模型类必须继承自
Django
的models.Model
类
1. 属性定义
-
格式
属性名 = models.字段类型(字段选项)
- 属性名不能是python的保留关键字
- 属性名不能使用连续的下划线(这是由django的查询方式决定的)
2. 关于主键
- 主键:primary key,简写 pk
- 不需要主动定义,django会自动生成自增长的主键,属性名叫
id
, - 如果开发者自己定义了主键,则django不会再生成默认的主键
3. 表名
- 默认为:应用名小写_模型类名小写
-
可通过通过
Meta
类指定表名,例如# 如果应用名为users,则默认表名为:users_department class Department(models.Model): ... class Meta: # 指定生成的数据库表的名字 db_table = 'department'
4. 字段类型
类型 | 说明 |
---|---|
AutoField | 自动增长的IntegerField,通常不用指定,不指定时Django会自动创建名为id的自动增长属性 |
BooleanField | 布尔字段,值为True或False |
NullBooleanField | 支持Null、True、False三种值 |
CharField | 字符串,必须指定:max_length ,表示最大字符个数 |
TextField | 大文本字段,一般超过4000个字符时使用 |
IntegerField | 整数 |
DecimalField | 十进制浮点数,用python中的Decimal实例来表示 必须指定: max_digits 最大位数,decimal_places 小数位数。 |
FloatField | 浮点数 |
DateField | 日期 1) 参数 auto_now 表示每次修改保存对象时,自动设置该字段为当前时间,用于保存"最后一次修改"时间,默认为False; 2) 参数 auto_now_add 表示当对象第一次被创建时自动设置保存当前时间,用于保存"创建时间"时间,默认为值为False; 3) 参数 auto_now_add 和auto_now 是相互排斥的,不能同时用到一个属性中 |
TimeField | 时间,参数同DateField |
DateTimeField | 日期时间,参数同DateField |
FileField | 上传文件字段 |
ImageField | 继承于FileField,对上传的内容进行校验,确保是有效的图片 |
4. 字段选项
选项 | 默认值 | 描述 | 是否要迁移修改表结构 |
---|---|---|---|
null | False | True表示表字段允许为空 | 是 |
unique | False | True表示表字段不能重复 | 是 |
db_column | 属性名称 | 表字段名称 | 是 |
primary_key | False | True表示字段设置为了主键,一般作为AutoField的选项使用 | 是 |
db_index | False | 创建索引 | 是 |
default | - | 默认值 | 否 |
blank | False | 在django管理后台新增或编辑一条表数据时,该字段是否允许为空; null是数据库范畴的概念,blank是表单验证范畴的 | 否 |
choices | - | 在django管理后台新增或编辑一条表数据时,该字段显示为下拉框,默认为编辑框 | 否 |
- choices: 性别属性使用了choices选项后,在录入一条数据时,会以下拉框显示
-
blank:blank属性默认值为false, 表示录入一条数据时,当前字段必须填写,不能为空,否则js端js校验不通过,例如:下图的comment员工备注信息字段。
5. 外键(关联属性)
在设置外键时,需要通过on_delete选项指明主表删除数据时,对于外键引用表数据如何处理,在django.db.models中包含了可选常量:
关联属性on_delete选项的取值
-
models.CASCADE
此为默认值,级联删除,会删除关联数据department = models.ForeignKey('Department', on_delete=models.CASCADE)
-
models.PROTECT
只要存在关联数据就不能删除department = models.ForeignKey('Department', on_delete=models.PROTECT)
-
models.SET_NULL
删除数据后关联字段设置为NULL,仅在该字段允许为null
时可用(null=True
)
二、代码参考
部门和员工模型类 代码参考
class Department(models.Model):
"""部门类"""
# 部门名称:字符串类型(必须要指定最大长度)
name = models.CharField(max_length=20)
# 部门成立时间: 日期类型
create_date = models.DateField(auto_now_add=True)
# 逻辑删除标识:标识部门是否删除
is_delete = models.BooleanField(default=False)
def __str__(self):
return self.name
class Meta:
# 指定表名
db_table = 'department'
class Employee(models.Model):
"""员工类"""
choices_gender = (
(0, '男'),
(1, '女'),
)
name = models.CharField(max_length=20)
age = models.IntegerField()
gender = models.IntegerField(default=0, choices=choices_gender)
# 工资:浮点类型(必须要指定两个选项) 999999.99
salary = models.DecimalField(max_digits=8, decimal_places=2)
# 备注信息: 可以为空
comment = models.CharField(max_length=300, null=True, blank=True)
# 员工入职时间
hire_date = models.DateField(auto_now_add=True)
# 一对多的外键:员工所属部门 department_id
department = models.ForeignKey('Department')
def __str__(self):
return self.name
class Meta:
# 指定表名
db_table = 'employee'
模型管理器
模型管理器:objects
属性
- 每个模型类默认都有一个叫
objects
的类属性,它由django自动生成 - 我们把
objects
称为 模型管理器,其类型为:django.db.models.manager.Manager
- 通过
objects
属性,可以实现对数据库相关的操作,常用方法如下
objects管理器中的方法 | 返回类型 | 作用 |
---|---|---|
模型类.objects.create() | 模型类对象 | 创建一个对象(新增一条数据) |
模型类.objects.get() | 模型对象 | 查询一个对象,且只能有一个: 如果查到多条数据,则报:MultipleObjectsReturned 如果查询不到数据,则报:DoesNotExist |
模型类.objects.all() | QuerySet | 查询所有的对象 |
模型类.objects.count() | 数字 | 查询总共有多少条数据 |
模型类.objects.filter() | QuerySet | 查询满足条件的对象 |
模型类.objects.exclude() | QuerySet | 查询不满条件的对象 |
模型类.objects.order_by() | QuerySet | 对查询结果集进行排序 |
模型类.objects.aggregate() | 字典,例如: {'salary__avg': 9500.0} | 进行聚合操作 Sum, Count, Max, Min, Avg |
数据增删改
1、增
-
模型类对象.save()
# 新增部门 d = Department() d.name = '人事部' d.create_date = '2017-1-1' d.save() # 新增员工 e = Employee() e.name = '龙五' e.age = 30 e.gender = 0 e.salary = 10000 # 注意关联属性的赋值 e.department = Department.objects.get(id=1) e.save()
-
模型类.objects.create(属性1=值1,属性2=值2, ...)
Department.objects.create( name='后勤部', create_date='2017-1-1' )
2、删
-
模型类对象.delete()
d = Department.objects.get(id=1) d.delete()
-
模型类.filter(条件).delete()
Department.objects.filter(id=1).delete()
关联属性on_delete选项的取值
-
models.CASCADE
此为默认值,级联删除,会删除关联数据department = models.ForeignKey('Department', on_delete=models.CASCADE)
-
models.PROTECT
只要存在关联数据就不能删除department = models.ForeignKey('Department', on_delete=models.PROTECT)
-
models.SET_NULL
删除数据后关联字段设置为NULL,仅在该字段允许为null
时可用(null=True
)
-
3、改
-
模型类对象.save()
# 方式一: 调用save方法 d = Department.objects.get(id=1) d.name = '人事部' d.save()
注意:
id
已存在,调用save
方法时为修改,否则为新增 -
模型类.filter(条件).update(属性1=值1,属性2=值2, ...)
Department.objects.filter(id=1).update(name='人事部')
查询
本节内容
- 条件查询
- F对象
- Q对象
- 聚合
- 排序
- 关联查询
一、条件查询
- 调用
filter方法
: 模型类.objects.filter(模型类属性名__条件名=值) - 返回包含查询结果数据的
QuerySet
对象
练习案例:
-
判等: exact
例:查询id为1的员工
select * from employee where id=1; Employee.objects.filter(id__exact=1) Employee.objects.filter(id=1)
-
模糊查询: contains / endswith / startswith
例:查询名字包含'马'的员工
select * from employee where name like '%马%'; Employee.objects.filter(name__contains='马') # 例:查询名字以'军'结尾的员工 select * from employee where name like '%军'; Employee.objects.filter(name__endswith='军')
-
空查询: isnull
例:查询备注信息不为空的员工
select * from employee where comment is not null ; Employee.objects.filter(comment__isnull=False)
-
范围查询: in
例:查询id编号为1或3或5的员工
select * from employee where id in (1, 3, 5); Employee.objects.filter(id__in=[1,3,5])
-
比较查询: gt(greater than)、lt(less than)、gte、lte
例:查询age大于等于30的员工
select * from employee where age >= 30; Employee.objects.filter(age__gte=30)
-
日期查询: year、month、day、week_day、hour、minute、second
例:查询2015年入职的员工
select * from employee where year(hire_date) = 2015; Employee.objects.filter(hire_date__year=2015) # 例:查询2014年1月1日后入职的员工 select * from employee where hire_date >= '2014-1-1'; Employee.objects.filter(hire_date__gte='2014-1-1')
二、exclude
方法
-
返回不满足条件的数据,用法: 模型类.objects.exclude(条件)
例:查询id不为3的员工
select * from employee where id != 3; Employee.objects.exclude(id=3)
三、F对象
之前的查询都是对象属性与常量值比较,如果要比较两个属性怎么做呢? 比如:查询语文分数大于数学分数的学生
姓名 | 数学 | 语文 | 英语 |
---|---|---|---|
Tom | 95 | 90 | 95 |
Jack | 95 | 90 | 95 |
Rose | 90 | 92 | 98 |
- F对象:比较表中的两个字段,接收的参数为一个字符串
-
用法:
F('属性名')
- 比如:
成绩表.objects.filter(语文__gt=F('数学'))
- 需要导包:
from django.db.models import F
- 比如:
-
案例
例:查询年龄大于id的员工信息(无实际意义)
select * from employee where age > id; Employee.objects.filter(age__gt=F('id')) # 例:查询年龄大于4倍id编号的员工信息 select * from employee where age > id * 4; Employee.objects.filter(age__gt=F('id') * 4 )
四、Q对象
- 作用: 对查询条件进行
与 或 非
(& | ~) 的逻辑操作 -
用法: 先导入
from django.db.models import Q
- 与: Q(查询条件1) & Q(查询条件2)
- 或: Q(查询条件1) | Q(查询条件2)
- 非: ~Q(查询条件)
-
案例
例:查询id大于3且年龄大于30的员工信息。
select * from employee where id > 3 and age > 30; Employee.objects.filter(id__gt=3, age__gt=30) Employee.objects.filter(Q(id__gt=3) & Q(age__gt=30)) # 例:查询id大于3或者年龄大于30的员工信息。 select * from employee where id > 3 or age > 30; Employee.objects.filter(Q(id__gt=3) | Q(age__gt=30)) # 例:查询id不等于3员工信息。 select * from employee where id != 3; Employee.objects.filter(~Q(id=3))
五、排序
- 作用: 对查询结果进行排序,默认为升序
-
用法:
升序: 模型类.objects.order_by('属性名')
降序: 模型类.objects.order_by('-属性名') -
示例:
例:查询所有员工信息,按照id从小到大进行排序。
select * from employee order by id asc; Employee.objects.order_by('id') # 例:查询所有员工信息,按照id从大到小进行排序。 select * from employee order by id desc; Employee.objects.order_by('-id') # 例:把id大于8的员工信息, 按年龄从大到小排序显示; select * from employee where id > 8 order by age desc; Employee.objects.filter(id__gt=8).order_by('-age')
六、aggregate
方法
- 作用: 聚合操作,对多行查询结果中的一列进行操作,返回一个值
-
用法: 模型类.objects.aggregate(聚合类('属性名'))
- 常用聚合类有:Sum, Count, Max, Min, Avg等
- 返回值是一个字典, 格式:
{'属性名__聚合函数': 值}
- 使用时需要先导入聚合类:
from django.db.models import Sum, Count, Max, Min, Avg
-
案例:
例:查询所有员工的平均工资
select avg(salary) from employee; Employee.objects.aggregate(Avg('salary'))
七、关联查询
一、通过 对象
进行关联查询
- 有关联属性(多对一查询):
模型类对象.关联属性
- 没有关联属性(一对多查询):
模型类对象.关联模型类类名小写_set.all()
# 查询 “研发部” 的所有员工
d = Department.objects.get(name='研发部')
d.employee_set.all()
# 例:查询 “赵小二” 所属的部门信息
e = Employee.objects.get(name='赵小二')
e.department
二、通过模型类
查询
模型类.objects.filter(关联属性__属性名__操作符=值)
模型类.objects.filter(关联模型类类名小写__属性名__操作符=值)
实现参考:
# 查询 “研发部” 的所有员工
Employee.objects.filter(department__name__exact='研发部')
# 例:查询 “赵小二” 所属的部门信息
Department.objects.filter(employee__name__exact='赵小二')