2012-03-12 19 views
18

Czy jest domyślnie dostępny filtr negacji? Chodzi o to, że można wykonać następujące czynności w ORM django:Filtr negatywów Tastypie

model.objects.filter(field!=value) 

Jak mogę to zrobić w tastypie jeśli to w ogóle możliwe. Próbowałem:

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

I wszystkie z nich dawały mi błędy.

+1

W niektórych przypadkach masz możliwość, aby zastąpić go z niektórych filtrów tak:? 'Field__not = null' można zastąpić' field__isnull = FALSE „_not większa than_” można zastąpić? po prostu '? field__lte = x' (czyli z" _less than equal_ "). Pamiętaj też, że Django może w jakiś sposób pozwolić ci przekazać 'field! = Value' jako argument, ale spowoduje to, że wartość boolowska zostanie przekazana dalej (lub' NameError' jeśli 'field' nie jest zdefiniowaną zmienną). Czy też się mylę i Django wykonuje przeciążenie operatora np. web2py działa w przypadku konstruktora zapytań? – Tadeck

Odpowiedz

27

Niestety, nie ma.

Problem polega na tym, że klasa ModelResource Tastypie używa metody filter() tylko w QuerySet, tzn. Nie używa metody exclude(), która powinna być używana w filtrach ujemnych. Nie ma szukania w filtrze(), które oznaczałoby negację. Poprawne wyszukiwań są (po tym 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 

Jednak to nie powinno być tak trudne do wdrożenia wsparcia dla czegoś podobnego „__not_eq”. Wszystko, co musisz zrobić, to zmodyfikować metodę apply_filters() i oddzielić filtry od "__not_eq" od reszty. Następnie powinieneś przekazać pierwszą grupę do exclude(), a resztę do filter().

Coś jak:

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) 

zamiast domyślnego:

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) 

powinno pozwolić na następującej składni:

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

ja jej nie testowane. To może być napisany prawdopodobnie w bardziej elegancki sposób też, ale powinno być ci :)

+0

Kluczem do filtru w negative_filters nie powinno być "field__not_eq", ale "field__exact", aby moduły ORM Django mogły sobie z nim poradzić. Ponadto, build_filters musi zostać nadpisany, aby "__not_eq" nie było postrzegane jako relacja przez Tastypie. – Wilerson

6

Innym sposobem, aby to zrobić bez zmian w kodzie jest użycie iregex z inverse matching

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

używam wykluczenia(), aby uniknąć pewnych wartości. Na przykład:

Person.filter(name="Tim").exclude(state="Down"); 
Powiązane problemy