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
不区分大小写的正则匹配

posted @ 2020-10-22 20:42  SoleMemory  阅读(136)  评论(0)    收藏  举报