2012-03-12 11 views
18

Esiste un filtro di negazione disponibile per impostazione predefinita. L'idea è che si può fare quanto segue nel ORM django:Filtro di negazione Tastypie

model.objects.filter(field!=value) 

Come posso farlo in tastypie se questo è ancora possibile. Ho provato:

someapi.com/resource/pk/?field__not=value 
someapi.com/resource/pk/?field__!=value 
someapi.com/resource/pk/?field!=value 

E tutti mi hanno dato errori.

+1

In alcuni casi si ha la possibilità di sostituirlo con alcuni filtri del genere: 'field__not = null' può essere sostituito con' field__isnull = false', "_non maggiore than_" può essere sostituito? semplicemente '? field__lte = x' (quindi con" _less than equal_ "). Inoltre, tieni presente che Django potrebbe in qualche modo consentire di passare 'field! = Value' come argomento, ma il valore booleano verrà passato ulteriormente (o' NameError' se 'field' non è una variabile definita). O mi sbaglio e Django esegue il sovraccarico dell'operatore come ad es. web2py fa in caso di query builder? – Tadeck

risposta

27

Purtroppo non c'è.

Il problema è che la classe ModelResource di Tastypie utilizza solo il metodo filter() di QuerySet, ovvero non utilizza exclude() che dovrebbe essere utilizzata per i filtri negativi. Non esiste una ricerca sul campo filter() che significherebbe negazione. Le ricerche sono validi (dopo questo SO post):

exact 
iexact 
contains 
icontains 
in 
gt 
gte 
lt 
lte 
startswith 
istartswith 
endswith 
iendswith 
range 
year 
month 
day 
week_day 
isnull 
search 
regex 
iregex 

Tuttavia non dovrebbe essere così difficile da attuare il supporto per qualcosa come "__not_eq". Tutto quello che devi fare è modificare il metodo apply_filters() e separare i filtri con "__not_eq" dal resto. Quindi devi passare il primo gruppo a exclude() e il resto a filter().

Qualcosa di simile:

def apply_filters(self, request, applicable_filters): 
    """ 
    An ORM-specific implementation of ``apply_filters``. 

    The default simply applies the ``applicable_filters`` as ``**kwargs``, 
    but should make it possible to do more advanced things. 
    """ 
    positive_filters = {} 
    negative_filters = {} 
    for lookup in applicable_filters.keys(): 
     if lookup.endswith('__not_eq'): 
      negative_filters[ lookup ] = applicable_filters[ lookup ] 
     else: 
      positive_filters[ lookup ] = applicable_filters[ lookup ] 

    return self.get_object_list(request).filter(**positive_filters).exclude(**negative_filters) 

al posto del default:

def apply_filters(self, request, applicable_filters): 
    """ 
    An ORM-specific implementation of ``apply_filters``. 

    The default simply applies the ``applicable_filters`` as ``**kwargs``, 
    but should make it possible to do more advanced things. 
    """ 
    return self.get_object_list(request).filter(**applicable_filters) 

dovrebbe consentire la seguente sintassi:

someapi.com/resource/pk/?field__not_eq=value 

non l'ho testato. Si potrebbe probabilmente essere scritto in modo più elegante troppo, ma dovrebbe farti andare :)

+0

La chiave per il filtro in negative_filters non deve essere "field__not_eq", ma "field__exact", quindi i moduli Django ORM possono gestirli. Inoltre, build_filters deve essere sovrascritto in modo che "__not_eq" non sia visto come una relazione da Tastypie. – Wilerson

6

Un altro modo per fare questo senza modifiche al codice è quello di utilizzare un iregex con inverse matching

http://HOST/api/v1/resource/?format=json&thing__iregex=^((?!notThis).)*$ 
-1

io uso escludere() per evitare alcuni valori. Per esempio:

Person.filter(name="Tim").exclude(state="Down");