关于 django orm 中 get 的 Exception

2015-04-17 13:27:22 +08:00
 happywowwow

使用django开发服务器,他的objects.get(pk=xxx) 或者objects.get(abc=xxx)得到的结果只能有且只有一条,不然是会报 DoesNotExist 或者 MultipleObjectsReturned 的错误。
如果没有防范措施,那这服务器不就挂了? 就会有一个500error
其他类似的queryset的方法也会有raise各种错误。
这怎么办?每次使用get都要catch这两个错误吗?
或者保证数据参数的正确性?

请教各位pythoner

7310 次点击
所在节点    Django
30 条回复
fishsjoy
2015-04-17 14:32:43 +08:00
get方法就是这么定义的。
主键的话不会出现MultipleObjectsReturned, DoesNotExist 可以用get_object_or_404。
当然,你可以用filter方法
happywowwow
2015-04-17 14:40:16 +08:00
@fishsjoy 如果有这样的表 id user_id team_id 可能有时候有这样的需求 result = objects.get(user_id=123, team_id=321) 如果有两条或者没有的话,就会有错了

不过想了想,这里是可以用filter代替
除了还是需要判断一下
result = objects.filter(user_id=123, team_id=321)
if not result:
return '404'
else:
result = result[0]
这样吗?
timonwong
2015-04-17 15:03:22 +08:00
@happywowwow
光是 filter 不够,因为还只是构建 QuerySet 阶段,这个 QuerySet 是 lazy 的,只有 get(), all(), slice 等操作才会触发。

你只有根据场景,catch IndexError (using slice) 或 DoesNotExist (using get()) 异常,
或者,使用 first()
happywowwow
2015-04-17 15:15:32 +08:00
@timonwong 啊,上面回复是写错了,应该还有一个.all()

我主题里的问题主要是每次使用这种会抛出异常的query方法,是不是都要放在try里面? 不然好像也没什么办法保证服务器不500?

除非除非,构建鲁棒的写入数据库的操作?
但感觉这难免有异常数据
virusdefender
2015-04-17 15:23:18 +08:00
get本来就是为了获取单条数据用的,如果你用filter的话,不也是需要判断获取的数据数据么,要不直接results[0]也会异常的。
yueyoum
2015-04-17 15:24:21 +08:00
!!!!!!!!!!!!!!!!!!!!!!!!!!!!

这个和 django orm 有毛关系啊!!!!!!!!!!!!

python 语言内建异常机制, 这是一种风格和哲学。
python代码就要这么写。


按照你的意思,是不是 python 的 buildin function: open 设计是错误的。
我 open一个不存在的文件, 居然会引发异常, 每次都要 try catch。。。



用 C 也好麻烦啊, 每次都要 判断 open/fopen 的返回值
yueyoum
2015-04-17 15:26:35 +08:00
上面补充一下 : 以 read 模式 open 一个不存在的文件
happywowwow
2015-04-17 16:28:34 +08:00
@virusdefender
@yueyoum
感谢两位
所以那些使用 get 的时候需要 catch 这两个 exception ,而 filter 出来的结果需要做一定判断,这是必不可少的了。
我之前的疑惑是有没有办法减少这样的操作,但看来是没有的。
为了服务器的鲁棒,使用get的时候还是都得加上 try catch 的了。
ericls
2015-04-17 16:33:53 +08:00
@happywowwow

`from django.shortcuts import get_object_or_404`
happywowwow
2015-04-17 16:52:17 +08:00
@ericls
感谢~

1、我知道这个api
2、如上一个需求,如果有这样的表三个字段,分别是id user_id team_id 可能有时候有这样的需求 result = objects.get(user_id=123, team_id=321) 如果有两条或者没有的话,就会有错了。这个表中user_id 字段和 team_id 都不是唯一的,但某一个user_id 或者 team_id 对应的结果理论上只能有一条(或没有),但出现多条的情况下,get_object_or_404 这个接口只能处理了 DoesNotExist 这个exception,但还是会报MultipleObjectsReturned。
3、我这rest api设计里面,返回json格式。是的,使用类似 get_object_or_404 这种封装的接口可能是我需要的,而这个封装可能需要我自己去做了~
chenxytw
2015-04-17 17:08:12 +08:00
话说。。。为什么不设置成unique = =也就从理论上避免了多条数据了出现
happywowwow
2015-04-17 17:15:48 +08:00
@chenxytw
啊哈,你没有看懂上面的需求吗?
如果有这样的表三个字段,分别是
id user_id team_id
0 1 1
1 1 2
2 2 1
3 1 2
4 3 1
5 1 3
1、只有id是唯一的
2、单个的 user_id,team_id都是可以重复的,也就不能是unique的,但是某一对(user_id, team_id)只能对应一条记录
happywowwow
2015-04-17 17:19:04 +08:00
@timonwong
啊哈,你说这个 filter 出来的 queryset 是 lazy 是没错的,但 filter 的结果在 if 比较的时候也会触发,不一定需要 all() slice
只有 filter 的 queryset 在bool 比较的时候也会触发。
参见 https://docs.djangoproject.com/en/1.5/ref/models/querysets/#when-querysets-are-evaluated
啊,所以之前我那没有 .all() 的代码也是可以执行的。。。
happywowwow
2015-04-17 17:20:23 +08:00
@chenxytw 啊 上面回复你的里面有一条重复了。。。写错了。。
1 1 2
3 1 2
Catstyle
2015-04-17 17:33:57 +08:00
啊哈,你需要的是unique_with?
Catstyle
2015-04-17 17:36:12 +08:00
哦,django orm里面是unique_together
happywowwow
2015-04-17 19:31:57 +08:00
@Catstyle 感谢! 有这个加了就更好了
chenxytw
2015-04-18 10:40:02 +08:00
@happywowwow
可以设置联合约束呀。。。。
已经建好的表 ALTER TABLE `table` ADD UNIQUE `unique_together`(`user_id `, `team_id`);
新表 CREATE TABLE `table` (id INT AUTO_INCREMENT PRIMARY KEY, user_id INT, team_id INT, UNIQUE `team_and_user_unique` (`user_id`, `team_id`));
happywowwow
2015-04-19 01:15:04 +08:00
@chenxytw 是的 现在就是这么对表做了处理。。。省得出错。。
happywowwow
2015-05-08 11:20:01 +08:00
@happywowwow 测试

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/184328

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX