django开发-QuerySet API总结

我们在开发中有时候可能会将QuerySet中的filter(), values(), first()等API返回的结果类型搞混淆,所以今天来总结一下django中与查询相关的API。下文中的序列化,都是指django_rest_framework中的序列化。

1.filter(): 返回一个QuerySet对象,包含是满足filter中筛选条件的models对象。


user_obj = UserInfoModel.objects.filter()
print("user objs:", type(user_obj))
for user in user_obj:
    print("user:", type(user))
user_ser = UserSerializer(instance=user_obj, many=True)
users = user_ser.data
return Response(dict(msg="OK", data=users))

调用filter()方法时,返回的结果如下:


user objs: <class 'django.db.models.query.QuerySet'>
user: <class 'user.models.UserInfoModel'>
user: <class 'user.models.UserInfoModel'>
user: <class 'user.models.UserInfoModel'>

filter()方法返回的QuerySet中,每个元素是models类型;并且由于返回的是QuerySet,序列化时需要加上many=True。

2.values(): 返回一个QuerySet对象,元素是dict


user_obj = UserInfoModel.objects.values()
print("user objs:", type(user_obj))
for user in user_obj:
    print("user:", type(user))

调用values()方法时,返回的结果如下:


user objs: <class 'django.db.models.query.QuerySet'>
user: <class 'dict'>
user: <class 'dict'>
user: <class 'dict'>

可以看到values()方法返回的QuerySet中,每个元素的类型是dict,那么获取属性值时,只能通过dict的相关方法来获取了,而不再是 对象.属性 的方式。

由于values()的结果仍然是QuerySet对象,所以还是可以通过序列化方式将结果返回给前端:


user_obj = UserInfoModel.objects.values()
print("user objs:", type(user_obj))
for user in user_obj:
    print("user:", user.get("username"))
user_ser = UserSerializer(instance=user_obj, many=True)
users = user_ser.data
return Response(dict(msg="OK", data=users))

也可以不通过序列化,直接返回给前端:


user_obj = UserInfoModel.objects.values()
print("user objs:", type(user_obj))
for user in user_obj:
    print("user:", user.get("username"))
# user_ser = UserSerializer(instance=user_obj, many=True)
# users = user_ser.data
return Response(dict(msg="OK", data=user_obj))

3.first(): 返回匹配的models对象中的第一个models对象


user_obj = UserInfoModel.objects.first()
print("user objs:", type(user_obj))
user_ser = UserSerializer(instance=user_obj)
users = user_ser.data
return Response(dict(msg="OK", data=users))

打印结果如下:


user objs: <class 'user.models.UserInfoModel'>

first()方法返回的是models对象,序列化时应该是many=False(默认)

4.all(): 返回所有model对象


user_obj = UserInfoModel.objects.all()
print("user objs:", type(user_obj))
for user in user_obj:
    print("user:", type(user))
user_ser = UserSerializer(instance=user_obj, many=True)
users = user_ser.data
return Response(dict(msg="OK", data=users))

all()方法与filter()方法返回的结果相同

5.get():满足筛选条件的对象必须只有一个,返回这个对象;当没有满足条件的models对象时,抛出models.DoesNotExist异常;有多个时也会抛出异常models.MultipleObjectsReturned.


user_obj = UserInfoModel.objects.get(id=1)
print("user objs:", type(user_obj))
user_ser = UserSerializer(instance=user_obj)
users = user_ser.data
return Response(dict(msg="OK", data=users))

打印结果:


user objs: <class 'user.models.UserInfoModel'>

可以看到,get()方法的返回结果也是models对象;但是,当get()返回的结果中有多个models对象时,就会报错;使用get()方法的前提是确保调用get()后只会返回一个models对象(可以在get()中添加约束条件)

6.exclude():返回一个QuerySet,包含那些与筛选条件不匹配的models对象。
1)例子如下


# 筛选出创建日期早于2019.01.31 11:59 的数据
user_obj1 = UserInfoModel.objects.exclude(create_time__gt=datetime.datetime(2019, 1, 31, 11, 59))
# 筛选出创建日期早于2019.01.31 的数据
user_obj2 = UserInfoModel.objects.exclude(create_time__gt=datetime.date(2019, 1, 31))
print("user_obj1:", user_obj1.query)
print("user_obj2:", user_obj2.query)
user_ser = UserSerializer(instance=user_obj1, many=True)
users = user_ser.data
return Response(dict(msg="OK", data=users))

执行exclude时,sql语句如下:


user_obj1: SELECT "user_info"."id", "user_info"."create_time", "user_info"."username", "user_info"."password", "user_info"."websites", "user_info"."url" FROM "user_info" WHERE NOT ("u
ser_info"."create_time" > 2019-01-31 11:59:00)
user_obj2: SELECT "user_info"."id", "user_info"."create_time", "user_info"."username", "user_info"."password", "user_info"."websites", "user_info"."url" FROM "user_info" WHERE NOT ("u
ser_info"."create_time" > 2019-01-31 00:00:00)

2)多个筛选条件
当exclude中有两个筛选条件时:


UserInfoModel.objects.exclude(create_time__gt=datetime.datetime(2019, 1, 31, 11, 59), id=1)

对应的sql语句如下:


SELECT "user_info"."id", "user_info"."create_time", "user_info"."username", "user_info"."password", "user_info"."websites", "user_info"."url" FROM "user_info" WHERE NOT ("u
ser_info"."create_time" > 2019-01-31 11:59:00 AND "user_info"."id" = 1)

注意这里是或者关系,满足其中一个条件就可以筛选出来

3)调用多个exclude
当调用多个exclude方法时:


UserInfoModel.objects.exclude(create_time__gt=datetime.datetime(2019, 1, 31, 11, 59)).exclude(id=1)

执行的sql如下:


SELECT "user_info"."id", "user_info"."create_time", "user_info"."username", "user_info"."password", "user_info"."websites", "user_info"."url" FROM "user_info" WHERE (NOT ("
user_info"."create_time" > 2019-01-31 11:59:00) AND NOT ("user_info"."id" = 1))

这里,这两个条件是并且的关系,两个条件都满足的数据才会被筛选出来。注意与上面的区别。

最后,推荐一篇介绍QuerySet和objects的博客:
https://blog.csdn.net/aaronthon/article/details/81714506