ORM使用
ORM框架
每个应用下的数据库模型类,需要在models.py来定义
一个数据库模型类相当于一个数据表(table)
数据库模型类必须继承Model或者Model子类
模型类中定义的类属性,一个类属性相当于一个数据表中的一个字段
Objects是用来操作数据库的接口
关系型字段
models.OneToOneField 一对一
models.ForeignKey 一对多
models.ManyToManyField 多对多
自关联
在一张数据表中一条记录关联到另一条记录,比如一张数据表中存储省市县,那么不同的省对应不同的县市,就需要用到自关联
# self可以改成模型类名称,比如AdressInfo,含义一样 pid = models.ForeignKey('self', null=True, black=True, verbose_name='自关联')
建表时一些字段释义:
ForeignKey
外键关联
第一个参数为‘应用名.模型类’或者import导入模型类直接作为参数
第二个参数on_delete,当父表(项目表)中的数据删掉之后,子表里这些字段的处理方式on_delete=models.CASCADE:表示父表字段删除之后,子表也会自动删除on_delete=models.SET_NULL:表示父表字段删除之后,子表的该字段自动设置为NULL,必须设置null=True和black=True
on_delete=models.DO_NOTHING:什么也不做
on_delete=models.SET_DEFAULT:将外键字段设为默认值,只有当字段设置了default参数时方可使用
on_delete=models.PROTECT:阻止上面的删除操作,但是弹出ProtectedError异常
on_delete=models.SET():用的少,设置一个传递给SET()的值或者一个回调函数的返回值
related_name
指定父表对子表引用名,如不指定,默认为子表模型类型名小写interfaces_set
verbose_name
可以设置更人性化的字段名,相当于别名,显示中文(在api接口文档中一些地方可以用到)
help_text
可以设置字段描述信息(在api接口文档中可以用到)
parimary_key=True
django默认会创建一个自增的id主键,如果手动创建了parimary_key=True ,那么django不会自动再创建自增的id(手动创建的目的是为了可以自己添加verbose_name help_text 等注释 )
unique
设置当前表的字段是否唯一,默认不唯一:unique=False
max_length
限制字段的最大长度
default
指定默认值
blank
用于设置在创建项目时前端可以不用传此字段,默认为false
null
用于设置数据库此字段是否可以为空,,默认为false,往往default,blank,null都一起来用
max_digits
总共多少位数字
deciaml_places
小数点后有多少位
db_column
自定义表的名称
db_index
等于True表示给这个字段建立索引
editable
等于False则表示用户无法对该字段内容进行编辑
以下为日期时间字段专用
unique_for_data
True表示日期只能是唯一
unique_for_month
True表示月份只能是唯一
auto_now
True表示更新记录时的当前时间,比如更新了一条记录,就是这个时间,会自动更新
auto_now_add
True表示增加记录时的当前时间,比如新插入了一条数据,就是这个时间,会自动更新
数据库迁移
python manage.py makemigrations 项目名称
生成数据库迁移脚本,项目名称可加可不加,不加就对所有子应用生效
python manage.py migrate 项目名称
执行迁移脚本
默认情况下,创建的表名为:子应用名_模型类名小写
注意如果已经在数据库创建好了表,又需要新增字段,需要指定默认值default(因为原来如果表中已经有数据,那么新增的字段不设置默认值django就不知道怎么处理)
如果不小心删除了部分的迁移记录,那么再迁移可能会失败,首先删除迁移历史记录,迁移的表,和migrations下面的py文件
更改数据库表结构后如何保留数据迁移
将app与数据库中的migrations目录和表下的记录删除,只保留__init__.py文件
数据导出
django 项目提供了一个导出的方法 python manage.py dumpdata, 不指定 appname 时默认为导出所有的app
python manage.py dumpdata [appname] > appname_data.json
数据库迁移
python manage.py makemigrations 和 python3 manage.py migrate;
数据导入,不需要指定 appname
python manage.py loaddata appname_data.json
优点:可以兼容各种支持的数据库,也就是说,以前用的是 SQLite3,可以导出后,用这种方法导入到 MySQL, PostgreSQL等数据库,反过来也可以。
缺点:数据量大的时候,速度相对较慢,表的关系比较复杂的时候可以导入不成功。
model定义字段释义
|
类型
|
说明
|
|
AutoField
|
一个自动增加的整数类型字段。通常你不需要自己编写它,Django会自动帮你添加字段:id = models.AutoField(primary_key=True),这是一个自增字段,从1开始计数。如果你非要自己设置主键,那么请务必将字段设置为primary_key=True。Django在一个模型中只允许有一个自增字段,并且该字段必须为主键!
|
|
IntegerField
|
整数类型,最常用的字段之一。取值范围-2147483648到2147483647。在HTML中表现为NumberInput标签,十一个字节
|
|
BigAutoField
|
(1.10新增)64位整数类型自增字段,数字范围更大,从1到9223372036854775807
|
|
BigIntegerField
|
64位整数字段(看清楚,非自增),类似IntegerField ,-9223372036854775808 到9223372036854775807。在Django的模板表单里体现为一个textinput标签。
|
|
SmallIntegerField
|
小整数,包含-32768到32767,六个字节
|
|
PositiveIntegerField
|
存储正整数,最大十个字节
|
|
PositiveSmallIntegerField
|
较小的正整数字段,从0到32767,五个字节
|
|
CommaSeparatedIntegerField
|
逗号分隔的整数类型。必须接收一个max_length参数。常用于表示较大的金额数目,例如1,000,000元。
|
|
FloatField
|
浮点数类型,参考整数类型
|
|
DecimalField
|
固定精度的十进制小数。相当于Python的Decimal实例,必须提供两个指定的参数!参数max_digits:最大的位数,必须大于或等于小数点位数 。decimal_places:小数点位数,精度。 当localize=False时,它在HTML表现为NumberInput标签,否则是text类型。例子:储存最大不超过999,带有2位小数位精度的数,定义如下:models.DecimalField(..., max_digits=5, decimal_places=2)。
|
|
BooleanField
|
布尔值类型。默认值是None。在HTML表单中体现为CheckboxInput标签。如果要接收null值,请使用NullBooleanField。
|
|
NullBooleanField
|
类似布尔字段,只不过额外允许NULL作为选项之一。
|
|
CharField
|
字符串类型。必须接收一个max_length参数,表示字符串长度不能超过该值。默认的表单标签是input text。最常用的filed,没有之一!
|
|
TextField
|
大量文本内容,在HTML中表现为Textarea标签,最常用的字段类型之一!如果你为它设置一个max_length参数,那么在前端页面中会受到输入字符数量限制,然而在模型和数据库层面却不受影响。只有CharField才能同时作用于两者。
|
|
DateField
|
class DateField(auto_now=False, auto_now_add=False, **options)日期类型。一个Python中的datetime.date的实例。在HTML中表现为TextInput标签。在admin后台中,Django会帮你自动添加一个JS的日历表和一个“Today”快捷方式,以及附加的日期合法性验证。两个重要参数:(参数互斥,不能共存) auto_now:每当对象被保存时将字段设为当前日期,常用于保存最后修改时间。auto_now_add:每当对象被创建时,设为当前日期,常用于保存创建日期(注意,它是不可修改的)。设置上面两个参数就相当于给field添加了editable=False和blank=True属性。如果想具有修改属性,请用default参数。例子:pub_time = models.DateField(auto_now_add=True),自动添加发布时间。
|
|
DateTimeField
|
日期时间类型。Python的datetime.datetime的实例。与DateField相比就是多了小时、分和秒的显示,其它功能、参数、用法、默认值等等都一样。
|
|
DurationField
|
持续时间类型。存储一定期间的时间长度。类似Python中的timedelta。在不同的数据库实现中有不同的表示方法。常用于进行时间之间的加减运算。但是小心了,这里有坑,PostgreSQL等数据库之间有兼容性问题!
|
|
EmailField
|
邮箱类型,默认max_length最大长度254位。使用这个字段的好处是,可以使用DJango内置的EmailValidator进行邮箱地址合法性验证。
|
|
FileField
|
class FileField(upload_to=None, max_length=100, **options)上传文件类型,后面单独介绍。
|
|
FilePathField
|
文件路径类型,后面单独介绍
|
|
ImageField
|
图像类型,后面单独介绍。
|
|
GenericIPAddressField
|
class GenericIPAddressField(protocol='both', unpack_ipv4=False, **options)[source],IPV4或者IPV6地址,字符串形式,例如192.0.2.30或者2a02:42fe::4在HTML中表现为TextInput标签。参数protocol默认值为‘both’,可选‘IPv4’或者‘IPv6’,表示你的IP地址类型。
|
|
SlugField
|
slug是一个新闻行业的术语。一个slug就是一个某种东西的简短标签,包含字母、数字、下划线或者连接线,通常用于URLs中。可以设置max_length参数,默认为50。
|
|
TimeField
|
时间字段,Python中datetime.time的实例。接收同DateField一样的参数,只作用于小时、分和秒。
|
|
URLField
|
一个用于保存URL地址的字符串类型,默认最大长度200。
|
|
UUIDField
|
用于保存通用唯一识别码(Universally Unique Identifier)的字段。使用Python的UUID类。在PostgreSQL数据库中保存为uuid类型,其它数据库中为char(32)。这个字段是自增主键的最佳替代品,后面有例子展示。
|
|
BinaryField
|
二进制数据类型。使用受限,少用。
|
queryset中一些常用的方法
|
方法名
|
解释
|
|
filter()
|
过滤查询对象。
|
|
exclude()
|
排除满足条件的对象
|
|
annotate()
|
使用聚合函数
|
|
order_by()
|
对查询集进行排序
|
|
reverse()
|
反向排序,需要在模型类元数据处执行ordering
|
|
exclude()
|
在查询出来的结果中去除该项指定的值
|
|
distinct()
|
对查询集去重
|
|
values()
|
返回包含对象具体值的字典的QuerySet
|
|
values_list()
|
返回包含对象具体值的列表,里面是元组
|
|
dates()
|
根据日期获取查询集
|
|
datetimes()
|
根据时间获取查询集
|
|
none()
|
创建空的查询集
|
|
all()
|
获取所有的对象
|
|
union()
|
并集
|
|
intersection()
|
交集,innodb支支持并集
|
|
difference()
|
差集,innodb支支持并集
|
|
select_related()
|
附带查询关联对象
|
|
prefetch_related()
|
预先查询
|
|
extra()
|
给字段取别名,比如extra(select={"name": "nickname"}),将nickname字段名改成name
|
|
defer()
|
不加载指定字段
|
|
only()
|
只加载指定的字段
|
|
using()
|
选择数据库
|
|
select_for_update()
|
锁住选择的对象,直到事务结束。
|
|
raw()
|
接收一个原始的SQL查询
|
不返回queryset的方法
|
方法名
|
解释
|
|
get()
|
获取单个对象
|
|
create()
|
创建对象,无需save()
|
|
get_or_create()
|
查询对象,如果没有找到就新建对象
|
|
update_or_create()
|
更新对象,如果没有找到就创建对象
|
|
bulk_create()
|
批量创建对象
|
|
count()
|
统计对象的个数
|
|
in_bulk()
|
根据主键值的列表,批量返回对象
|
|
iterator()
|
获取包含对象的迭代器
|
|
latest()
|
获取最近的对象
|
|
earliest()
|
获取最早的对象
|
|
first()
|
获取第一个对象
|
|
last()
|
获取最后一个对象
|
|
aggregate()
|
聚合操作
|
|
exists()
|
判断queryset中是否有对象
|
|
update()
|
批量更新对象
|
|
delete()
|
批量删除对象
|
|
as_manager()
|
获取管理器
|
aggregate()方法详解:
aggregate的中文意思是聚合, 源于SQL的聚合函数。Django的aggregate()方法作用是对一组值(比如queryset的某个字段)进行统计计算,并以字典(Dict)格式返回统计计算结果
django的aggregate方法支持的聚合操作有AVG / COUNT / MAX / MIN /SUM 等。
如:计算学生平均年龄, 返回字典。
Student.objects.all().aggregate(Avg('age'))
annotate()方法详解:
annotate的中文意思是注释,更好的理解是分组(Group By)。如果你想要对数据集先进行分组然后再进行某些聚合操作或排序时,需要使用annotate方法来实现。
与aggregate方法不同的是,annotate方法返回结果的不仅仅是含有统计结果的一个字典,而是包含有新增统计字段的查询集(queryset).
如:按学生分组,统计每个学生的爱好数量
Student.objects.annotate(Count('hobbies'))
使用 annotate() 组合多个聚合将产生错误的结果( yield the wrong results ),因为它使用连接(joins)而不是子查询, 对大部分聚合来说,没办法避免这个问题,但是,Count 聚合可以使用 distinct 参数来避免:
Book.objects.annotate(Count('authors', distinct=True), Count('store', distinct=True))
aggregate() 不同的是,annotate() 不是终端子句。annotate() 子句的输出就是 QuerySet;这个 QuerySet 被其他 QuerySet 操作进行修改,包括 filter(), order_by() ,甚至可以对 annotate() 进行额外调用
Annotate方法与Filter方法联用
有时我们需要先对数据集先筛选再分组,有时我们还需要先分组再对查询集进行筛选。根据需求不同,我们可以合理地联用annotate方法和filter方法。注意: annotate和filter方法联用时使用顺序很重要。
先按爱好分组,再统计每组学生数量, 然后筛选出学生数量大于1的爱好。
Hobby.objects.annotate(student_num=Count('student')).filter(student_num__gt=1)
查询参数及聚合函数
|
exact
|
精确匹配
|
|
iexact
|
不区分大小写的精确匹配
|
|
contains
|
包含匹配
|
|
icontains
|
不区分大小写的包含匹配
|
|
in
|
在..之内的匹配
|
|
gt
|
大于
|
|
gte
|
大于等于
|
|
lt
|
小于
|
|
lte
|
小于等于
|
|
startswith
|
从开头匹配
|
|
istartswith
|
不区分大小写从开头匹配
|
|
endswith
|
从结尾处匹配
|
|
iendswith
|
不区分大小写从结尾处匹配
|
|
range
|
范围匹配
|
|
date
|
日期匹配
|
|
year
|
年份
|
|
month
|
月份
|
|
day
|
日期
|
|
week
|
第几周
|
|
week_day
|
周几
|
|
time
|
时间
|
|
hour
|
小时
|
|
minute
|
分钟
|
|
second
|
秒
|
|
isnull
|
判断是否为空
|
|
search
|
1.10中被废弃
|
|
regex
|
区分大小写的正则匹配
|
|
iregex
|
不区分大小写的正则匹配
|
浙公网安备 33010602011771号