2013-01-04 10 views
6

esempio abbastanza semplice - ho un po 'di codice di Django che inizia con un set di query ...A che punto sono le eccezioni sollevate quando si utilizza ORM di Django

queryset = MyModel.objects.all() 

In seguito si esegue varie filtraggio, a seconda alcuni configurabile opzioni ...

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

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

E infine esegue la ricerca ...

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

Ora, essere A causa del modo flessibile in cui deve avvenire il filtraggio, è possibile che le variabili some_foo o some_bar non siano del tipo corretto (ad es. potremmo finire con una stringa vuota che tenta di filtrare su un campo intero.) quindi è possibile che questo codice finisca per generare un TypeError o un ValueError.

va bene, e posso gestire il caso in modo appropriato, ma ciò che non mi è chiaro dal contratto ORM, è a che punto devo aspettarmi tali eccezioni da sollevare.

  • verrà in mente sulla dichiarazione .filter()? ...
  • ... o sulla dichiarazione .get()? ...
  • ... o è in underspecified, e mi occupo come in grado di si verificano su entrambi? (Ad esempio, forse in base alla realizzazione del terminale database?)
+0

forse mi manca qualcosa, ma ho bisogno di chiedere: perché stai chiamando salire sul queryset? filter() e get() hanno scopi diversi e entrambi eseguono una query. e filter() è il primo a eseguire una query -> l'errore Type/Value verrà generato durante il filtraggio. non si raggiunge il get() –

+0

Nota: Va bene, posso vedere in questo caso particolare che sembra essere sollevato dall'istruzione '.get()' (che è quello che mi aspettavo), ma non è chiaro se posso tranquillamente fare affidamento su questo comportamento per essere coerenti. –

+0

@SamueleMattiuzzo Le istruzioni filtro possono essere concatenate. Il finale '.get()' è il bit che esegue la ricerca di un singolo oggetto, data la query. –

risposta

1

Per rispondere alla domanda iniziale, un FieldError e ValueError sono sollevati sulla chiamata per filtrare, in caso di nuove queryset è costruito:

>>> 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' 

Aggiungerò anche che questo schema mi sembra fuorviante, in quanto filter viene normalmente utilizzato per restituire un elenco/iterabile di modelli, anziché uno come con get. Per chiarezza e una più facile gestione delle eccezioni, suggerirei questo schema:

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') 

L'altro vantaggio è che, IIRC, il lavoro di set di query di clonazione è relativamente costoso, in modo da ignorare che in testa, mentre al stesso tempo rendendo il codice più pulito. Tornando alla tua domanda, con questo schema non c'è dubbio dove verrà sollevata l'eccezione.

+0

Il pattern 'kwargs' probabilmente è più bello. L'eccezione 'FieldError' (nome campo errato) è un caso leggermente diverso da 'TypeError' (tipo errato fornito al filtro). Il primo sembra che si verifichi immediatamente, ma sembra che ciò accada più tardi quando la ricerca viene effettivamente effettuata. Tuttavia, accetterò la risposta poiché penso che il modello kwarg sia il modo giusto per affrontare l'ambiguità. –

Problemi correlati