6

足够简单的例子 - 我有一些以查询集开头的 Django 代码......

queryset = MyModel.objects.all()

稍后它会执行各种过滤,具体取决于一些可配置的选项......

if something:
    queryset = self.queryset.filter(foo=some_foo)

if another_thing:
    queryset = self.queryset.filter(bar=some_bar)

最后它执行查找...

try:
    obj = queryset.get()
except ObjectDoesNotExist:
    raise ValidationError('Does not exist')

现在,由于过滤需要以灵活的方式进行,因此some_fooorsome_bar变量可能不是正确的类型(例如,我们最终可能会得到一个空字符串来尝试过滤整数字段。)所以这是可能的此代码最终会引发 aTypeError或 a ValueError

没关系,我可以适当地处理此案,但是从 ORM 合同中我不清楚的是,我应该在什么时候提出这些例外。

  • 它会出现在.filter()声明中吗?...
  • ...或在.get()声明中?...
  • ...或未指定,我将其处理为能够发生在任何一个上?(例如,可能取决于数据库后端的实现?)
4

1 回答 1

1

为了回答原始问题,在构建新查询集时,在调用过滤器时会引发aFieldError和:ValueError

>>> a = Account.objects.all()
>>> a = a.filter(id=3)
>>> a = a.filter(no_exist=3)
<snip>
FieldError: Cannot resolve keyword 'no_exist' into field. Choices are: active, created_on, group, id, ...

>>> a = Account.objects.all()
>>> a = a.filter(id='abc')
ValueError: invalid literal for int() with base 10: 'abc'

我还要补充一点,这种模式对我来说似乎具有误导性,因为filter它通常用于返回模型的列表/可迭代,而不是get. 为了清楚和更容易地处理异常,我建议使用这种模式:

kwargs = {}
if something:
    kwargs['foo'] = some_foo
if another_thing:
    kwargs['bar'] = some_bar

# handle if kwargs is empty
try:
    obj = MyModel.objects.get(**kwargs)
except (FieldError, ValueError, ObjectDoesNotExist):
    raise ValidationError('Does not exist')

另一个额外的好处是,IIRC,克隆查询集的工作相对昂贵,因此您可以忽略该开销,同时使代码更清晰。回到您的问题,使用这种模式,毫无疑问会在哪里引发异常。

于 2013-01-05T01:21:13.297 回答