¿Cómo hago una no es igual en el filtrado queryset Django?
-
22-08-2019 - |
Pregunta
En QuerySets modelo de Django, veo que hay una __gt
y __lt
para valores Comparativos, pero hay una __ne
/ !=
/ <>
( no iguales ?)
Quiero filtrar utilizando un no es igual a:
Ejemplo:
Model:
bool a;
int x;
Quiero
results = Model.objects.exclude(a=true, x!=5)
El !=
no es la sintaxis correcta. Probé __ne
, <>
.
Terminé usando:
results = Model.objects.exclude(a=true, x__lt=5).exclude(a=true, x__gt=5)
Solución
Tal vez los objetos Q podría ser de ayuda para este problema. Nunca los he usado, pero parece que pueden ser anulados y se combinan al igual que las expresiones pitón normales.
Actualización: Sólo probé, parece que funciona bastante 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>, ...]
Otros consejos
Su consulta parece tener una doble negación, desea excluir todas las filas donde x no es 5, por lo que en otras palabras quiere incluir todas las filas donde x es 5. Creo que esto va a hacer el truco.
results = Model.objects.filter(x=5).exclude(a=true)
Para responder a su pregunta específica, no existe "no es igual a", pero eso es probablemente porque Django tiene tanto "filtro" y "excluir" métodos disponibles para que siempre puede cambiar la lógica redonda para obtener el resultado deseado.
field=value
la sintaxis de las consultas es una abreviatura de field__exact=value
. Esto quiere decir que Django pone operadores de consulta en los campos de la consulta en el identificadores . Django soporta los siguientes operadores:
exact
iexact
contains
icontains
in
gt
gte
lt
lte
startswith
istartswith
endswith
iendswith
range
year
month
day
week_day
isnull
search
regex
iregex
Estoy seguro de que mediante la combinación de estos con los objetos como Q de Dave Vogt sugiere y usando filter()
o exclude()
como Jason Baker sugiere que obtendrá exactamente lo que necesita para cualquier consulta posible.
Es fácil crear una búsqueda personalizada con Django 1.7. Hay un ejemplo de búsqueda en __ne
Django documentación oficial .
Es necesario crear las operaciones de búsqueda en sí primero:
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
Luego hay que registrarlo:
from django.db.models.fields import Field
Field.register_lookup(NotEqual)
Y ahora usted puede utilizar la búsqueda __ne
en sus consultas como esto:
results = Model.objects.exclude(a=True, x__ne=5)
Django 1.9 / 1.10 hay tres opciones.
-
results = Model.objects.exclude(a=true).filter(x=5)
-
Q()
objetos y la~
from django.db.models import Q object_list = QuerySet.filter(~Q(a=True), x=5)
-
El registro de un función
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
El decorador
register_lookup
se añadió en Django 1.8 y permite que las operaciones de búsqueda personalizada como de costumbre:results = Model.objects.exclude(a=True, x__ne=5)
Mientras que con los modelos, puede filtrar con =
, __gt
, __gte
, __lt
, __lte
, no se puede utilizar ne
, !=
o <>
. Sin embargo, se puede lograr un mejor filtrado sobre el uso del objeto Q.
Usted puede evitar el encadenamiento QuerySet.filter()
y QuerySet.exlude()
, y usar esto:
from django.db.models import Q
object_list = QuerySet.filter(~Q(field='not wanted'), field='wanted')
A la espera de decisión de diseño. Mientras tanto, el uso exclude()
El seguimiento de incidencias Django tiene la notable entrada # 5763 , titulado "queryset no tiene una '' operador de filtro" no igual . Es notable porque (a partir de abril de 2016) era "Abrió hace 9 años" (en la edad de piedra Django), "Cerrado hace 4 años", y "Última cambiado hace 5 meses".
Leer a través de la discusión, es interesante.
Básicamente, algunas personas sostienen __ne
debe añadirse
mientras que otros dicen exclude()
es más clara y por lo tanto __ne
debe no que añadir.
(estoy de acuerdo con el anterior, ya que este último argumento es
más o menos equivalente a decir Python no debería tener porque !=
tiene ==
y not
ya ...)
Debe utilizar filter
y exclude
como esto
results = Model.objects.exclude(a=true).filter(x=5)
El uso de excluir y filtro
results = Model.objects.filter(x=5).exclude(a=true)
El último bit de código excluirá todos los objetos donde x! = 5 y A es verdadero. Prueba esto:
results = Model.objects.filter(a=False, x=5)
Recuerde, el signo = en la línea de arriba es asignar Falso para el parámetro A y el número 5 al parámetro x. No es la comprobación de la igualdad. Por lo tanto, no hay realmente ninguna manera de utilizar el! = Símbolo en una llamada de consulta.
Lo que busca son todos los objetos que tienen ya sea a=false
o x=5
. En Django, |
sirve como operador OR
entre QuerySets:
results = Model.objects.filter(a=false)|Model.objects.filter(x=5)
results = Model.objects.filter(a = True).exclude(x = 5)Generetes este SQL: SQL
select * from tablex where a != 0 and x !=5The depende de cómo se representa su / campo Falso Verdadero, y el motor de base de datos. El código de Django es todo lo que necesita sin embargo.
Django-modelo-valores (divulgación: autor) proporciona una implementación de la NotEqual de búsqueda, como en esta respuesta. También proporciona soporte sintáctico para ello:
from model_values import F
Model.objects.exclude(F.x != 5, a=True)
Tenga cuidado con un montón de respuestas incorrectas a esta pregunta!
La lógica de Gerard es correcta, aunque se devolverá una lista en lugar de un conjunto de consultas (que podría no importa).
Si usted necesita un conjunto de consultas, utilice Q:
from django.db.models import Q
results = Model.objects.filter(Q(a=false) | Q(x=5))