ORM的增删改查
在进行模型操作的学习之前,可以先创建一个测试的数据库模型类,如下所示
class Person(models.Model): name = models.CharField(max_length=10,verbose_name="姓名") age = models.IntegerField(verbose_name="年龄")
创建对象
django 自带了一个数据库测试的 shell 工具,这是一个非常方便可以让我们对 django 代码进行测试的环境
可以直接通过python manage.py shell命令行管理工具来打开
实例 save 创建数据
通过模型类的关键词参数实例化一个对象来进行数据的创建
>>> from app.models import Person >>> p1 = Person(name='张三',age=15) >>> p1.save()
以上的代码,在为字段赋予值之后,通过实例的 save 函数进行该数据的保存 在数据库底层执行了SQL语句中的insert操作,并且,在我们显示调用save之前,django不会访问数据库,实例数据只存在于内存中
-
注意:save函数没有返回值
create 方法创建数据
>>> P1 = Person.objects.create(name='李四',age=20)
这条语句创建一条数据,并且返回一个数据在内存中的实例 P1,之后可以通过这个实例字段 P1 对数据库中该条数据进行修改或删除操作 create方法一步到位,save方式可以慢悠悠的赋予字段值,最后赋予结束再 save
查找对象
接下来,我们将通过模型类中的管理器进行数据的查询;
管理器(Manager)是每一个模型类所具有的,默认名为objects,模型类通过模型类调用orm数据接口,其实就是在对数据表进行操作
注意,具体的某一条数据无法访问这个管理器
-
all()
获取一个表中的所有数据,返回QuerySet数据对象
all_person = Person.objects.all()
-
filter(**kwargs)
返回一个包含数据对象的集合,满足参数中所给的条件
res = Person.objects.all().filter(age__lt=16) res = Person.objects.filter(age__lt=16)
我们在查询过程中,除了直接使用字段属性进行验证 还可以在字段名之后使用双下化线来标明更加详细的字段筛选条件(在下一节会有详细的字段筛选条件介绍),也叫做链式过滤
这也是为什么表单类字段不可以以下换线结尾的原因
-
exclude(**kwargs)
返回一个包含数据对象的集合,数据为不满足参数中所给的条件
filter()查询会始终返回一个结果集,哪怕只有一个数据,但是有些时候,我们对于一些在数据表中的唯一数据进行查询时,可以使用更加合适的get方法
-
get(**kwargs)
获取唯一单条数据
get 获取数据只会返回一条匹配的结果,获取的数据只能在数据库中有一条
如果返回多个结果,会引发MultipleObjectsReturned异常;如果没有任何匹配到的结果也会引发DoesNotExist异常
Person.objects.get(pk=1)
-
order_by(*field)
默认情况下,数据表使用模型类中的 Meta 中指定的 ordering 选项进行排序 也可以通过使用 order_by 函数进行查询结果的排序
Person.objects.order_by('age')
Person.objects.all().order_by('-age')
-
count()
返回数据库中对应字段的个数,并且该函数永远不会引发异常
models.Person.objects.filter(age=20).count() Person.objects.count()
使用count函数时,还需要对数据表进行迭代访问 *注意:所以有时使用已生产好的结果集,通过len函数获取长度,这种方式效率会更高;count方法的调用会导致额外的数据库查询
-
values(*fields)
返回一个查询集结果,但是迭代访问时返回的是字典,而不是数据实例对象
models.Person.objects.all().values() models.Person.objects.values()
链式过滤条件
-
contains
大小写敏感的匹配查询,也是 like,注意转换后查询条件的两侧都有%
Person.objects.filter(name__contains='好')
-
icontains
大小写不敏感的匹配查询
Person.objects.filter(name_icontains='好')
-
range
在某个范围内进行查询
Person.objects.filter(id_range=(1,6))
-
in
查询条件是否在给定的范围内,用小括号和中括号都可以
Person.objects.filter(id_in=(1,6)) Person.objects.filter(id_in=[1,6])
-
exact
如果在查询过程中,没有提供查询类型(没有双下划线),那么查询类型就会被默认指定为exact,这是一种严格查找的方式,用来在数据库中查找和查询时的关键词参数完全一致的内容
Person.objects.filter(account='root') Person.objects.filter(account__exact='root')
-
iexact
忽略大小写的匹配
Person.objects.filter(account__iexact='root') #匹配到的结果可能是 Root,ROot,ROOt,ROOT
-
startswith、endswith
分别匹配开头和结尾,区分大小写
Person.objects.filter(passwd__startswith='admin') # 匹配以 admin 开头的数据
-
istartswith、iendswith
分别匹配开头和结尾,忽略大小写
Person.objects.filter(passwd__istartswith='admin') 匹配以不区分大小写的字符串 admin 为开头的数据
-
gte
大于或等于
Person.objects.filter(reg_data__gte=datetime.date.today)
-
lte
小于或等于
Person.objects.filter(reg_data__lte=datetime.date.today)
修改对象
获取到对应的数据实例之后,通过.的方式访问数据实例中的属性,进行数据的字段修改,修改之后通过save方法对实例进行入库的保存
p = models.Person.objects.get(pk=1) p.age = 21 p.save()
对过滤出的结果链式调用update()函数,这样的修改,类似批量修改,update函数会返回成功修改的个数
models.Person.objects.filter(age__gt=100).update(age=25) # 将所有年纪小于 100 的人的年纪改为 20
删除对象
对于普通的单表数据删除,获取到数据实例对象后调用内置的delete()函数即可
models.Person.objects.get(pk=1).delete()
-
注意:删除一条数据之后,默认占有的主键 ID 值并不会被下一个新插入的值所占用
比如 1,2,3,4;删除掉 3 之后,剩下:1,2,4;下一个值存储时,id 是 5,3 不会被复用



