2012-03-12 4 views
18

Y at-il un filtre de négation disponible par défaut. L'idée est que vous pouvez faire ce qui suit dans le django ORM:Filtre de négation Tastypie

model.objects.filter(field!=value) 

Comment puis-je faire dans tastypie si cela est encore possible. J'ai essayé:

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

Et tous m'ont donné des erreurs.

+1

Dans certains cas, vous avez la possibilité de le remplacer par des filtres comme ça: 'field__not = null' peut être remplacé par' field__isnull = false', « _pas plus than_ » peut être remplacé? par juste '? field__lte = x' (donc avec" _less than equal_ "). Aussi, gardez à l'esprit que Django peut vous permettre de passer 'field! = Value' comme argument, mais cela entraînera une valeur booléenne plus longue (ou' NameError' si 'field' n'est pas une variable définie). Ou ai-je tort et Django effectue une surcharge de l'opérateur comme par exemple. web2py le fait en cas de constructeur de requête? – Tadeck

Répondre

27

Malheureusement, il n'y en a pas. Le problème est que la classe ModelResource de Tastypie utilise uniquement la méthode filter() du QuerySet, c'est-à-dire qu'elle n'utilise pas exclude() qui doit être utilisé pour les filtres négatifs. Il n'y a aucune recherche de champ de filtre() qui signifierait la négation cependant. Les recherches valides sont (après 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 

Cependant, il ne devrait pas être si difficile à mettre en œuvre le soutien à quelque chose comme « __not_eq ». Tout ce que vous devez faire est de modifier la méthode apply_filters() et séparer les filtres avec "__not_eq" du reste. Ensuite, vous devez passer le premier groupe à exclude() et le reste à filter().

Quelque chose comme:

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) 

au lieu de la valeur par défaut:

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) 

devrait permettre la syntaxe suivante:

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

Je ne l'ai pas testé. Il pourrait probablement être écrit plus élégante trop, mais si vous y aller :)

+0

La clé du filtre dans negative_filters ne doit pas être "field__not_eq", mais "field__exact", donc les modules ORM de Django peuvent le gérer. De plus, les filtres de construction doivent être remplacés de sorte que "__not_eq" ne soit pas considéré comme une relation par Tastypie. – Wilerson

6

Une autre façon de le faire sans changement de code est d'utiliser un iregex avec inverse matching

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

J'utilise exclure() pour éviter certaines valeurs. Par exemple:

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