V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
happywowwow
V2EX  ›  Django

关于 django orm 中 get 的 Exception

  •  1
     
  •   happywowwow · 2015-04-17 13:27:22 +08:00 · 7318 次点击
    这是一个创建于 3509 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

    请教各位pythoner

    30 条回复    2015-05-08 18:32:41 +08:00
    fishsjoy
        1
    fishsjoy  
       2015-04-17 14:32:43 +08:00   ❤️ 1
    get方法就是这么定义的。
    主键的话不会出现MultipleObjectsReturned, DoesNotExist 可以用get_object_or_404。
    当然,你可以用filter方法
    happywowwow
        2
    happywowwow  
    OP
       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
        3
    timonwong  
       2015-04-17 15:03:22 +08:00   ❤️ 1
    @happywowwow
    光是 filter 不够,因为还只是构建 QuerySet 阶段,这个 QuerySet 是 lazy 的,只有 get(), all(), slice 等操作才会触发。

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

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

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

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

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


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



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

    `from django.shortcuts import get_object_or_404`
    happywowwow
        10
    happywowwow  
    OP
       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
        11
    chenxytw  
       2015-04-17 17:08:12 +08:00
    话说。。。为什么不设置成unique = =也就从理论上避免了多条数据了出现
    happywowwow
        12
    happywowwow  
    OP
       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
        13
    happywowwow  
    OP
       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
        14
    happywowwow  
    OP
       2015-04-17 17:20:23 +08:00
    @chenxytw 啊 上面回复你的里面有一条重复了。。。写错了。。
    1 1 2
    3 1 2
    Catstyle
        15
    Catstyle  
       2015-04-17 17:33:57 +08:00   ❤️ 1
    啊哈,你需要的是unique_with?
    Catstyle
        16
    Catstyle  
       2015-04-17 17:36:12 +08:00
    哦,django orm里面是unique_together
    happywowwow
        17
    happywowwow  
    OP
       2015-04-17 19:31:57 +08:00
    @Catstyle 感谢! 有这个加了就更好了
    chenxytw
        18
    chenxytw  
       2015-04-18 10:40:02 +08:00   ❤️ 1
    @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
        19
    happywowwow  
    OP
       2015-04-19 01:15:04 +08:00
    @chenxytw 是的 现在就是这么对表做了处理。。。省得出错。。
    happywowwow
        20
    happywowwow  
    OP
       2015-05-08 11:20:01 +08:00
    @happywowwow 测试
    eric6356
        21
    eric6356  
       2015-05-08 11:37:58 +08:00
    eric6356
        22
    eric6356  
       2015-05-08 11:38:25 +08:00
    eric6356
        23
    eric6356  
       2015-05-08 11:39:43 +08:00
    eric6356
        24
    eric6356  
       2015-05-08 11:39:57 +08:00
    happywowwow
        25
    happywowwow  
    OP
       2015-05-08 11:40:20 +08:00
    happywowwow
        26
    happywowwow  
    OP
       2015-05-08 11:41:00 +08:00
    happywowwow
        27
    happywowwow  
    OP
       2015-05-08 18:31:43 +08:00
    happywowwow
        28
    happywowwow  
    OP
       2015-05-08 18:32:08 +08:00
    @happywowwow test111
    happywowwow
        29
    happywowwow  
    OP
       2015-05-08 18:32:25 +08:00
    happywowwow
        30
    happywowwow  
    OP
       2015-05-08 18:32:41 +08:00
    @eric6356 77777
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5974 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 30ms · UTC 03:25 · PVG 11:25 · LAX 19:25 · JFK 22:25
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.