Comment puis-je faire un pas égal dans le filtrage Django queryset?
-
22-08-2019 - |
Question
Dans le modèle Django QuerySets, je vois qu'il ya un __gt
et __lt
pour les valeurs Comparitive, mais est-il un __ne
/ !=
/ <>
( pas égaux ?)
Je veux filtrer à l'aide d'une égale pas:
Exemple:
Model:
bool a;
int x;
Je veux
results = Model.objects.exclude(a=true, x!=5)
Le !=
n'est pas une syntaxe correcte. J'ai essayé __ne
, <>
.
Je fini par utiliser:
results = Model.objects.exclude(a=true, x__lt=5).exclude(a=true, x__gt=5)
La solution
Peut-être objets Q pourrait être utile à ce problème. Je ne les ai jamais utilisé, mais il semble qu'ils peuvent être réduits à néant et combinés beaucoup comme expressions python normales.
Mise à jour: Je l'ai essayé, il semble fonctionner assez 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>, ...]
Autres conseils
Votre requête semble avoir un double négatif, vous voulez exclure toutes les lignes où x est pas 5, donc en d'autres termes que vous voulez inclure toutes les lignes où x est 5. Je crois que cela va faire l'affaire.
results = Model.objects.filter(x=5).exclude(a=true)
Pour répondre à votre question, il n'y a pas « pas égal à » mais c'est probablement parce que django a à la fois « filtre » et « exclure » les méthodes disponibles de sorte que vous pouvez toujours passer autour de la logique pour obtenir le résultat souhaité.
la syntaxe field=value
dans les requêtes est un raccourci pour field__exact=value
. C'est-à-dire que Django met les opérateurs de requête sur les champs de requête dans la 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 suggère et Vogt en utilisant filter()
ou exclude()
comme Jason Baker suggère que vous obtiendrez exactement ce dont vous avez besoin pour à peu près toute question possible.
Il est facile de créer une recherche personnalisée avec Django 1.7. Il y a un exemple de recherche de __ne
dans Django documentation officielle .
Vous devez créer la recherche elle-même d'abord:
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 vous pouvez maintenant utiliser la __ne
recherche dans vos requêtes comme ceci:
results = Model.objects.exclude(a=True, x__ne=5)
Django 1.9 / 1.10 il y a trois options.
-
results = Model.objects.exclude(a=true).filter(x=5)
-
Utilisez des objets
Q()
opérateur~
from django.db.models import Q object_list = QuerySet.filter(~Q(a=True), x=5)
-
Enregistrer un recherche personnalisée fonction
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 décorateur
register_lookup
a été ajouté dans Django 1.8 permet la recherche personnalisée comme d'habitude:results = Model.objects.exclude(a=True, x__ne=5)
Alors que 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 sur l'utilisation de l'objet Q.
Vous pouvez éviter enchaînant QuerySet.filter()
et QuerySet.exlude()
, et utiliser ceci:
from django.db.models import Q
object_list = QuerySet.filter(~Q(field='not wanted'), field='wanted')
En attendant la décision de conception. Pendant ce temps, l'utilisation exclude()
Le suivi des problèmes Django a l'entrée remarquable # 5763 , intitulé « queryset ne dispose pas d'un « » opérateur filtre » pas égal . Il est remarquable (en Avril 2016), il a été « Ouvert il y a 9 ans » (à l'âge de pierre Django), « Fermé il y a 4 ans », et "Dernière modification il y a 5 mois".
Lire par la discussion, il est intéressant.
En fait, certaines personnes affirment __ne
devrait être ajouté
tandis que d'autres disent exclude()
est plus claire et donc __ne
devrait pas ajouter.
(Je suis d'accord avec le premier, parce que ce dernier argument est
à peu près équivalent à dire Python ne devrait pas avoir !=
parce que
il a ==
et not
déjà ...)
Vous devez utiliser filter
et exclude
comme ceci
results = Model.objects.exclude(a=true).filter(x=5)
Utilisation et exclure filtre
results = Model.objects.filter(x=5).exclude(a=true)
Le dernier morceau de code exclura tous les objets où x! = 5 et est vrai. Essayez ceci:
results = Model.objects.filter(a=False, x=5)
Rappelez-vous, le signe = dans la ligne précédente est d'attribuer False au paramètre a et du nombre 5 au paramètre x. Il n'est pas la vérification de l'égalité. Ainsi, il n'y a pas vraiment un moyen d'utiliser le! = Symbole dans un appel de requête.
Ce que vous cherchez sont tous les objets qui ont soit a=false
ou x=5
. Dans Django, |
sert opérateur OR
entre QuerySets:
results = Model.objects.filter(a=false)|Model.objects.filter(x=5)
results = Model.objects.filter(a = True).exclude(x = 5)Generetes cette sql:
select * from tablex where a != 0 and x !=5The sql dépend de la façon dont votre champ Vrai / Faux est représenté, et le moteur de base de données. Le code est django tout ce que vous devez bien.
Django-modèle-valeurs (divulgation: auteur) fournit une implémentation de la NotEqual de la recherche, comme dans cette réponse . Il fournit également un soutien syntaxique pour elle:
from model_values import F
Model.objects.exclude(F.x != 5, a=True)
Méfiez-vous beaucoup de réponses incorrectes à cette question!
La logique de Gérard est correct, mais il retournera une liste plutôt que d'un queryset (qui pourrait ne pas d'importance).
Si vous avez besoin d'un queryset, utilisez Q:
from django.db.models import Q
results = Model.objects.filter(Q(a=false) | Q(x=5))