Question Comment puis-je faire un filtrage de jeux de requêtes Django non égal?


Dans le modèle QuerySets de Django, je vois qu'il y a un __gt et __lt pour des valeurs comparables, mais y a-t-il un __ne/!=/<> (pas égal?)

Je veux filtrer en utilisant un non égal:

Exemple:

Model:
    bool a;
    int x;

je veux

results = Model.objects.exclude(a=true, x!=5)

le != n'est pas la syntaxe correcte. j'ai essayé __ne, <>.

J'ai fini par utiliser:

results = Model.objects.exclude(a=true, x__lt=5).exclude(a=true, x__gt=5)

504
2018-03-26 19:47


origine


Réponses:


Peut être Q objets pourrait être utile pour ce problème. Je ne les ai jamais utilisés, mais il semble qu'ils puissent être niés et combinés comme des expressions python normales.

Mise à jour: Je viens de l'essayer, ça semble marcher plutôt bien:

>>> from myapp.models import Entry
>>> from django.db.models import Q

>>> Entry.objects.filter(~Q(id = 3))

[<Entry: Entry object>, <Entry: Entry object>, <Entry: Entry object>, ...]

521
2017-07-20 17:58



Votre requête semble avoir un double négatif, vous voulez exclure toutes les lignes où x n'est pas 5, donc en d'autres termes, vous voulez inclure toutes les lignes où x IS 5. Je crois que cela fera l'affaire.

results = Model.objects.filter(x=5).exclude(a=true)

Pour répondre à votre question spécifique, il n'y a pas de "non égal à", mais c'est probablement parce que django a à la fois les méthodes "filtre" et "exclure", vous pouvez donc toujours changer la logique pour obtenir le résultat souhaité.


470
2017-11-09 23:56



la field=value la syntaxe dans les requêtes est un raccourci pour field__exact=value. C'est-à-dire que Django place les opérateurs de requête sur les champs de requête dans les identificateurs. Django prend en charge les opérateurs suivants:

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

Je suis sûr en combinant ceux-ci avec les objets Q comme Dave Vogt suggère et en utilisant filter() ou exclude() comme Jason Baker suggère vous obtiendrez exactement ce dont vous avez besoin pour n'importe quelle requête.


98
2017-07-20 18:07



Il est facile de créer une recherche personnalisée avec Django 1.7. Il y a un __ne exemple de recherche dans Django documentation officielle.

Vous devez d'abord créer la recherche:

from django.db.models import Lookup

class NotEqual(Lookup):
    lookup_name = 'ne'

    def as_sql(self, qn, connection):
        lhs, lhs_params = self.process_lhs(qn, connection)
        rhs, rhs_params = self.process_rhs(qn, connection)
        params = lhs_params + rhs_params
        return '%s <> %s' % (lhs, rhs), params

Ensuite, vous devez l'enregistrer:

from django.db.models.fields import Field
Field.register_lookup(NotEqual)

Et maintenant vous pouvez utiliser le __ne recherche dans vos requêtes comme ceci:

results = Model.objects.exclude(a=True, x__ne=5)

66
2018-03-24 08:07



Dans Django 1.9 / 1.10 il y a trois options.

  1. Chaîne exclude et filter

    results = Model.objects.exclude(a=true).filter(x=5)
    
  2. Utilisation Q() objets et le ~ opérateur

    from django.db.models import Q
    object_list = QuerySet.filter(~Q(a=True), x=5)
    
  3. Enregistrer un fonction de recherche personnalisée

    from django.db.models import Lookup
    from django.db.models.fields import Field
    
    @Field.register_lookup
    class NotEqual(Lookup):
        lookup_name = 'ne'
    
        def as_sql(self, compiler, connection):
            lhs, lhs_params = self.process_lhs(compiler, connection)
            rhs, rhs_params = self.process_rhs(compiler, connection)
            params = lhs_params + rhs_params
            return '%s <> %s' % (lhs, rhs), params
    

    le register_lookup décorateur a été ajouté dans Django 1.8 et active la recherche personnalisée comme d'habitude:

    results = Model.objects.exclude(a=True, x__ne=5)
    

55
2018-02-24 13:12



Avec les modèles, vous pouvez filtrer avec =, __gt, __gte, __lt, __lte, vous ne pouvez pas utiliser ne, != ou <>. Cependant, vous pouvez obtenir un meilleur filtrage en utilisant l'objet Q.

Vous pouvez éviter d'enchaîner QuerySet.filter() et QuerySet.exlude()et utilisez ceci:

from django.db.models import Q
object_list = QuerySet.filter(~Q(field='not wanted'), field='wanted')

39
2018-01-18 14:34



Décision de conception en attente Pendant ce temps, utilisez exclude()

Le tracker de problème de Django a le remarquable entrée # 5763, titré "Queryset n'a pas d'opérateur de filtre" pas égal "". C'est remarquable parce que (en avril 2016) c'était "ouvert il y a 9 ans" (à l'âge de pierre de Django), "fermé il y a 4 ans", et "Dernière modification il y a 5 mois".

Lisez la discussion, c'est intéressant. Au fond, certaines personnes se disputent __ne devrait être ajouté tandis que d'autres disent exclude() est plus clair et donc __ne devrait ne pas être ajouté.

(Je suis d'accord avec le premier, car le dernier argument est à peu près équivalent à dire Python ne devrait pas avoir !=car il a == et not déjà...)


14
2018-04-21 08:44



Tu devrais utiliser filter et exclude comme ça

results = Model.objects.exclude(a=true).filter(x=5)

12
2017-09-25 08:52



Le dernier bit de code exclura tous les objets où x! = 5 et a est vrai. Essaye ça:

results = Model.objects.filter(a=False, x=5)

Rappelez-vous que le signe = dans la ligne ci-dessus attribue la valeur False au paramètre a et le chiffre 5 au paramètre x. Ce n'est pas la vérification de l'égalité. Ainsi, il n'y a vraiment aucun moyen d'utiliser le symbole! = Dans un appel de requête.


7
2018-03-26 19:54



Ce que vous recherchez sont tous des objets qui ont soit a=false  ou  x=5. Dans Django, | sert OR opérateur entre les querysets:

results = Model.objects.filter(a=false)|Model.objects.filter(x=5)

3
2018-06-27 12:50