Django ORM详解
ORM
ORM,对象关系映射, 对象和关系之间的映射。这样就可以使用面向对象的方式来操作数据库中的表。
ORM 的主要目的是将数据库操作抽象成面向对象的操作,使得开发者可以使用 Python 代码而不是 SQL 语句来执行数据库操作
Model模型
字段类型
字段类 | 说明 |
---|---|
AutoField | 自增的整数字段。 如果不指定,django会为模型类自动增加主键字段 |
BooleanField | 布尔值字段,True和False 对应表单控件CheckboxInput |
NullBooleanField | 比BooleanField多一个null值 |
CharField | 字符串,max_length设定字符长度 对应表单控件TextInput |
TextField | 大文本字段,一般超过4000个字符使用 对应表单控件Textarea |
IntegerField | 整数字段 |
BigIntegerField | 更大整数字段,8字节 |
DecimalField | 使用Python的Decimal实例表示十进制浮点数。max_digits总位数, decimal_places小数点后的位数 |
FloatField | Python的Float实例表示的浮点数 |
DateField | 使用Python的datetime.date实例表示的日期 对应控件为TextInput,关联了一个Js编写的日历控件 auto_now=True 每次修改对象被保存 save() 时,自动设置为当前时间。更新场景(最后修改时间)auto_now_add=True 仅在对象第一次创建时,自动设置为当前时间,之后不在更改(创建时间) |
TimeField | 使用Python的datetime.time实例表示的时间,参数同上 |
DateTimeField | 使用Python的datetime.datetime实例表示的时间,参数同上 |
FileField | 一个上传文件的字段 |
ImageField | 继承了FileField的所有属性和方法,但是对上传的文件进行校验,确保是一个有效的图片 |
EmailField | 能做Email检验,基于CharField,默认max_length=254 |
GenericIPAddressField | 支持IPv4、IPv6检验,缺省对应文本框输入 |
URLField | 能做URL检验,基于CharField,默认max_length=200 |
缺省主键
缺省情况下,Django的每一个Model都有一个名为 id 的AutoField字段,如果显式定义了主键,这种缺省主键就不会被创建了
字段选项
字段 | 说明 |
---|---|
db_column | 表中字段的名称。如果未指定,则使用属性名 |
primary_key | 是否主键 |
unique | 是否是唯一键 |
default | 缺省值。这个缺省值不是数据库字段的缺省值,而是新对象产生的时候被填入的缺省值 |
null | 表的字段是否可为null,默认为False |
blank | Django表单验证中,是否可以不填写,默认为False |
db_index | 字段是否有索引 |
verbose_name | 可视化的名字,即字段的可读名称 |
choices | 提供枚举值,每一项枚举值是二元组 (value, label) ,其中 value 是存储在数据库中的实际值,而 label 用于在界面上显示 |
关系类型字段类
字段 | 说明 |
---|---|
ForeignKey | 外键,表示一对多 to_field 选项表示关联到主表的哪个字段,默认使用主键 on_delete 选项表示选择哪个外键约束操作 ForeignKey('production.Manufacturer') 自关联 ForeignKey('self') |
ManyToManyField | 表示多对多 Django会自动创建第三张表来管理这个多对多的关系,这个中间表包含了两个外键,分别指向参与多对多关系的两个模型。 默认情况下,这个表的名字是 <model>_tablename 如果想要自定义中间表,通过 through 参数指定一个自定义的中间模型 |
OneToOneField | 表示一对一 |
管理器
管理器非常重要,有了它才能操作数据库。即增删改查
每一个非抽象的Model类必须有一个Manager实例。如果不指定,Django会默认指定一个Manager,就是属性objects。
Django查询
查询集
如果查的是一批数据,那么返回的是一个结果的集合,即查询集,是 django.db.models.query.QuerySet
的实例,也是可迭代对象。
查询集是惰性查值,创建查询集不会带来任何对数据库的访问,直到调用方法使用数据时,才会访问数据库。
每一个查询集都包含一个缓存,来最小化对数据库的访问。首次对查询集遍历求值时,会发生数据库查询,Django会把查询的结果存在这个缓存中,并返回请求的结果,接下来对改查询集求值将使用缓存的结果。
限制查询集
限制查询集,即查询集对象可以直接使用索引下标的方式(不支持负索引),相当于SQL语句中的 limit 和 offset 子句,在分页功能中适用。
下例方法中,如果返回值如果是QuerySet类型,可以链式调用
结果集方法
名称 | 返回值类型 | 说明 | 举例 |
---|---|---|---|
all() | QuerySet | 返回全部数据 | Employee.objects.all() |
filter() | QuerySet | 过滤,返回满足条件的数据,可以指定多条过滤条件 | Employee.objects.filter(pk=10010).values() |
exclude() | QuerySet | 排除,排除满足条件的数据 | Employee.objects.exclude(emp_no=10001) |
order_by() | QuerySet | 排序,注意参数是字符串,‘-’ 表示降序 | Employee.objects.exclude(emp_no=10002).order_by('-pk') |
values() | QuerySet | 返回集合内的元素是字典,字典内是字段和值的键值对 | Employee.objects.values() |
返回单个值的方法
名称 | 说明 | 举例 |
---|---|---|
get() | 严格返回满足条件的单个实例对象 如果未能返回对象则抛出DoesNotExist异常; 如果能返回多条,抛出MultipleObjectsReturned异常 | Employee.objects.filter(pk=10010).get() |
count() | 返回当前查询的总条数 | Employee.objects.count() |
first() | 返回第一个实例对象 | Employee.objects.first() |
last() | 返回最后一个实例对象 | Employee.objects.exclude(pk=10010).last() |
exist() | 判断查询集中是否有数据,如果有则返回True | Employee.objects.exists() |
字段查询(Field Lookup)表达式
字段查询表达式可以作为filter()、exclude()、get()的参数,实现where子句
语法:属性名称__比较运算符 = 值
(双下划线)
名称 | 举例 | 说明 |
---|---|---|
exact | filter(isdeleted=False) filter(isdeleted__exact=False) | 严格等于,可省略不写 |
contains | exclude(title__contains='天') | 是否包含,大小写敏感 等价于 like binary '%天%' 模糊匹配效率很低 |
startswith endswith | filter(title__startswith='天') | 以什么开头或结尾,大小写敏感 |
isnull isnotnull | filter(title__isnull=False) | 是否为null |
iexact icontains istartswith iendswith | i 的意思是忽略大小写 | |
in | filter(pk__in=[1,2,3,100]) | 是否在指定范围数据中 |
gt、gte lt、lte | filter(id__gt=3) filter(pk__lte=6 ) filter(pub_date__gt=date(2000,1,1)) | 大于、小于等 |
year month day week_day hour minute second | filter(pub_date__year=2000) | 对日期类型属性处理 |
Django增删改
增加:create(字段名1=value, 字段名2=value, ...)
更新:update(字段名=value)
删除:delete()