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_fooまたはsome_bar変数が正しいタイプではない可能性があります (たとえば、整数フィールドに対してフィルタリングしようとすると、空の文字列になる可能性があります)。このコードが aTypeErrorまたは aを上げることになりValueErrorます。

それは問題ありません。ケースを適切に処理できますが、ORM コントラクトから明らかでないのは、これらの例外がどの時点で発生することを期待すべきかということです。

  • 明細書上で発生するの.filter()でしょうか? ...
  • ...または.get()ステートメントで?...
  • ...または指定不足であり、どちらでも発生する可能性があるとして処理しますか? (例えば、おそらくデータベース バックエンドの実装に依存しますか?)
4

1 に答える 1

1

元の質問に答えるために、新しいクエリセットが構築されると、フィルターの呼び出しでFieldErrorとが発生します。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')

もう 1 つの追加の利点は、IIRC、クエリセットのクローン作成の作業は比較的高価であるため、そのオーバーヘッドを無視すると同時に、コードをよりクリーンにすることです。質問に戻りますが、このパターンでは、例外が発生する場所に疑問はありません。

于 2013-01-05T01:21:13.297 に答える