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()