model:模型
models使用了ORM技术
Object Relational Mapping 对象关系映射
在django中就是对数据操作的封装。
在model中 可以对数据库的表结构进行定义:
创建模型类——在数据库中对应生成的表
定义类属性——对应数据库中表的字段
模型的定义
需要继承自系统的models.Model
在定义时同时可以在class Meta() 元信息定义db_table 表名——在数据库中生成的表名
class ModelName(models.Model):
pass
class Meta:
db_table = 'new_tablename' # 对数据库中生成的表名进行重定义
定义字段
定义模型的字段即定义model 的属性:
格式:
模型属性(字段名) = models.字段属性(字段约束)
字段属性:
CharField
字符串
TextField
大内容的字符串
IntegerField
数字
FloatField
浮点
DecimalField
精准的浮点
BooleanField
布尔
NullBooleanField
空布尔
AutoField
自增
FileField
文件
ImageField
图片
字段约束
max_length
最大长度
default
默认值
unique
唯一性
index
索引
primary_key
主键 唯一
db_column
重命名
将定义好的模型映射到数据库中:
生成迁移文件
python manage.py makemigrations
执行迁移
python manage.py migrate
前提
数据库配置完毕
默认配置的SQLite
自主配置的MySQL
引擎(ENGINE)
数据库名字(NAME)
用户名(USER)
密码(PASSWORD)
主机(HOST)
端口(PORT)
驱动,需要伪装 #驱动一般定义在__init__.py文件中
在django项目的__init__文件中添加
pymysql.install_as_MySQLdb()
迁移思路:
分两步实现:
1.生成迁移文件,
2.执行迁移文件。
迁移文件的生成:
根据models文件生成对应的迁移文件
根据models和已有迁移文件差别,生成新的迁移文件
执行迁移文件
先去迁移记录查找,那些文件未迁移过
app_label+迁移文件名字
执行未迁移的文件
执行完毕,记录执行过的迁移文件
重新迁移:
删除迁移文件
删除迁移文件产生的表
删除迁移记录
将数据库中已存在的表在django.models中创建模型:
python manage.py inspectdb
会将生成的model打印出来
python manage.py inspectdb > APP.models.py
逆向从数据库获取表数据在models.py中生成class(若不定向输出时则直接在打印中输出内容)
可以直接根据表生成模型
迁移系统不管的class
如果自己的某个模型不想被迁移系统管理,也可以在元信息中使用manage=False声明
元信息中包含一个属性 :
class Meta:
managed = False
通过model实现对数据库的增删改查:
增:
CREATE
instance.save()
创建对象
直接实例化对象,设置属性
创建对象,传入属性
用实例化对象调用save方法,完成创建
查:
retrieve
查询句柄——object
具体操作:
获取查询结果集 QuertSet
model类.objects.all() 获取对应表中所有的数据
model类.objects.filter() 根据条件进行筛选,返回符合条件的查询结果集。括号中传入筛选条件
model类.objects.exclude() 根据条件进行筛选,返回不符合条件的查询结果集。括号中传入筛选条件
model类.objects.order_by() 根据字段对饮的属性按升序排序,括号内传入字段/属性名,若需要降序排序,在字段名前加 - 即可
model类.objects.values() 返回的queryset中每一项是一个字典
切片[n,m]
不支持负数
实际上相当于limit offset
懒查询
观察者模型
发布者,订阅者
广播
获取单个对象
model类.objects.get()
括号内传入筛选条件
不存在会抛异常 DoesNotExist
存在多于一个也会抛异常 MultipleObjectReturned
使用这个函数记得捕获异常
last
first
可能出现第一个和最后一个是一样的
需要主动进行排序
筛选条件
属性__操作符=临界值
操作符:
gt 大于
gte 大于等于
lt 小于
lte 小于等于
in 存在于某个范围中,范围需要传入的值是一个列表
exact 精确等于
startswith 以...开头
endswith 以...结尾
contains 包含...
ignore 忽略大小写
iexact 精确等于,忽略大小写
istartswith 以...开头,忽略大小写
iendswith 以...结尾,忽略大小写
icontains 包含...,忽略大小写
条件升级
F方法
获取字段信息
通常用在模型的自我属性比较
支持算数运算
company = Company.object.filter(c_boy_num__lt=F(c_girl_num))
# 获取boy_num小于girl_num的company数据集合
Q方法
条件封装
支持逻辑运算
与 &
或 |
非 ~
companys = Company.objects.filter(Q(c_boy_num__gt=1) & Q(c_girl_num__gt=10))
# 获取boy_num大于1,同时girl_num大于10的company数据集合
内置函数
查询结果集.count() 返回查询结果数量
查询结果集exists() 判断查询结果是否存在,是返回True,否返回False
改
update
基于查询结果,直接用赋值的方式更改数据,然后调用save保存即可
删
DELETE
基于查询结果,使用查询结果调用.delete()函数即可
在企业中,对于重要数据的删除处理,一般来说是不会做物理删除的。采用逻辑删除的方法,通过在数据库表中定义一个is_delete
字段来判断数据时候还可用。
model对象的属性
属性分为两种:
显性属性
开发者手动声明的属性
隐性属性
没有声明,父类中也不存在,动态产生出来的
如果手动声明了隐性属性=,则系统不会再自动生成了
Django中的模型关系
一对一:
应用场景:
用于复杂表的拆分
扩展新功能
定义字段属性models.OneToOneField
确认主从关系
底层实现:从表中声明外键并添加唯一约束
一对一的模型关系下 数据获取操作:
从获取主:通过显性属性
主获取从:通过隐性属性
默认就是从表模型名小写
获取从表属性集合:
主表模型名.从表模型名小写_set
一对一关系下删除数据:
从表数据删除
主表数据不受影响
主表删除数据时需要根据设置外键时的参数来判断如何删除:
在django2.0后,定义外键和一对一关系的时候需要加on_delete选项,此参数为了避免两个表里的数据不一致问题,不然会报错:
TypeError: init() missing 1 required positional argument:
on_delete有CASCADE、PROTECT、SET_NULL、SET_DEFAULT、SET()五个可选择的值
models.CASCADE:此值设置,是级联删除。
models.PROTECT:此值设置,删除数据时会报完整性错误。
models.SET_NULL:此值设置,会把外键设置为null,前提是允许为null
models.SET_DEFAULT:此值设置,会把设置为外键的默认值。
models.SET():此值设置,会调用外面的值,可以是一个函数。
一般情况下使用CASCADE就可以了。
通过外键获取集合
def get_student(request):
# 获取符合主表筛选条件primary key=1的从表数据
grade = Grade.objects.get(pk=1)
# 通过外键获取符合条件的从表的数据集合 [主表.从表_set.all()]
students = grade.student_set.all()
context = {'students': students,}
return render(request, 'App2_home.html', context=context)
通过在models.py中定义对应类的类方法来自定义对应表字段的默认值等属性,类方法不会映射到数据库表中
一对多
直接使用外键实现
主从结构,多是在从表中声明关系
级联对象获取;
主从获取:
主获取从:隐性属性,级联模型(类名小写)_set
student_set Manager的子类
all
filter
aexclude
Manager上能使用的函数都能使用
从获取主:
通过显性属性获取
数据删除同一对一
多对多
两张以上的表的对应关系
会产生额外的关系表
表中使用多个外键实现
外键对应关系表的主表
数据获取
两张表的结构一样
从获取主
Manage对象
all
filter
exclude
操作级联数据
add
remove
clear
set
显性属性
主获取从
隐性属性
Manage对象
和其他Manage一样
django中的模型继承
模型继承
默认一个模型在数据库中映射一张表
如果模型存在继承的时候,父模型产生表映射
子模型对应的表会通过外键和父表产生关联
关系型数据库性能:
数据量越大性能越低
关系越多越复杂性能越低
抽象模型
在Model的元信息(class Meta:)中添加 abstract=True
抽象的模型不会在数据库中产生表
子模型拥有父模型的所有字段