Django中QuerySet与Model对象的操作陷阱及正确用法解析
本文深入解析Django中filter()返回的QuerySet与get()返回的Model对象在数据操作上的核心差异。重点指出直接修改QuerySet无法同步至数据库的原因,并提供通过first()或[0]获取实例后调用save()的正确更新方案。同时对比filter与get在空值处理、类型匹配及批量更新时的行为差异,帮助开发者避免常见ORM使用错误。
首先通过代码示例进行说明。
观察以下代码片段:
示例1:
message = Message.objects.filter(pk=message_id2) message[0].id = message_id2 message[0].content = content2 message[0].message_type = message_type2 print(message[0].id) print(message[0].content) message[0].save()
上述代码能够正常从QuerySet中读取数据并打印,运行无误。然而,这种操作无法将修改后的数据同步回数据库。
(1)调用all()方法返回的是QuerySet对象。此时程序并未真正在数据库中执行SQL查询,但该对象支持迭代操作,因此可以通过for循环遍历获取数据。
假设存在一个Book表,包含bookname和booknum两个字段,探讨如何利用Objects.all()方法获取这两个字段的值。
(2)filter()方法同样返回QuerySet对象,其行为与all()类似。区别在于,all()用于查询所有数据,而filter()常用于表示“等于”条件的查询,exclude()则用于表示“不等于”。
(3)get()方法返回的是具体的Model对象(注意:原文称类型为列表,实际应为单个模型实例,此处保留原意但修正表述以符合技术事实,即直接获取数据)。使用get方法会立即执行SQL语句从数据库获取数据。
观察一个QuerySet对象的示例:

message = Message.objects.filter(pk=message_id2) message[0].content
虽然可以读取到QuerySet中的数据,但对QuerySet对象进行修改后,这些更改无法保存到数据库。
在示例1中,不要尝试通过message.save()来同步数据到数据库,因为QuerySet对象本身不存在save()方法。
正确的写法如下:
若要将数据同步到数据库中,必须使用具体的模型对象进行数据同步操作。
示例2:
message = Message.objects.filter(pk=message_id2).first() message.id = message_id2 message.content = content2 message.message_type = message_type2 message.save()
补充知识:关于Django中filter和get的个人使用体会。
开发环境配置:Ubuntu 16.04 + Django 1.11.9 + Python 2.7。
filter返回的是QuerySet对象:
filter返回的是QuerySet,支持切片和遍历操作;而get不支持,因为get旨在获取唯一存在的数据,若不存在或存在多条记录,get会抛出异常。
当没有符合条件的记录时:
get方法会报错。
Book matching query does not exist.
而filter则返回一个空的QuerySet列表,不会报错。
<QuerySet []>`
代码可以继续往下执行。
判断filter是否有值时:
book_info = Book.objects.filter(id=book_id, request_type=2)
queryset.exists() if book_info.exists():
queryset.count==0: if queryset.count>0: pass else: pass
if queryset: if queryset: pass else: pass
filter在某些情况下也会报错:
当filter字段类型为int时,若传入的参数却是str类型,会引发报错:
invalid literal for int() with base 10: 'Yu'
使用get时,若遇到相同情况,错误信息与上述filter报错一致。
当filter字段存在,但filter不到对应值时:
输出结果为:<QuerySet []>
当结果为空时,自然不能通过[0]进行取值操作。
在使用filter作为过滤条件更新数据时:
Book.objects.filter(id=book_id, request_type=2).order_by("-time")[0].update(result=note)
该操作会报错:
'Book' object has no attribute 'update'
使用filter不能进行部分更新,必须更新所有符合条件的记录(注:此处原文逻辑有误,update是QuerySet方法,但报错是因为调用了[0]后的Model对象无update方法,下文修正为正确逻辑)。
但是可以使用[0]获取符合过滤条件的第一个值。
解决办法是使用save()方法:
book_info = Book.objects.filter(id=book_id, request_type=2).order_by("-time")[0]
book_info.result = note
book_info.save()
filter字段后常见的
这里是双下划线,即__。
__gt 大于 __gte 大于等于 __lt 小于 __lte 小于等于 __contains 包含 __icontains 包含 忽略大小写 __startswith 以...开头 __istartswith 以...开头 忽略大小写 __endswith 以...结尾 __iendswith 以...结尾,忽略大小写
以上关于Django中使用filter()(即对QuerySet操作)时遇到的坑的分享就是全部内容,希望能给大家一个参考,也希望大家多多支持本站。
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













