python - queries - ¿Cómo hago una no igual en el filtrado de Django queryset?
orm django queries (13)
Decisión de diseño pendiente. Mientras tanto, use exclude()
El rastreador de problemas de Django tiene la notable entrada # 5763 , titulada "Queryset no tiene un" operador de filtro "no igual" . Es notable porque (a partir de abril de 2016) se "abrió hace 9 años" (en la edad de piedra de Django), "se cerró hace 4 años" y "se modificó por última vez hace 5 meses".
Leer a través de la discusión, es interesante. Básicamente, algunas personas argumentan que se debe agregar __ne
, mientras que otros dicen que exclude()
es más claro y, por __ne
tanto, no se debe agregar __ne
.
(Estoy de acuerdo con el primero, porque el último argumento es aproximadamente equivalente a decir que Python no debería tener !=
Porque tiene ==
y aún not
...)
En el modelo Django QuerySets, veo que hay un __gt
y un __lt
para los valores comparativos, pero hay un __ne
/ !=
/ <>
(¿ No es igual a ?)
Quiero filtrar utilizando un no es igual a:
Ejemplo:
Model:
bool a;
int x;
quiero
results = Model.objects.exclude(a=true, x!=5)
La !=
No es la sintaxis correcta. Intenté __ne
, <>
.
Terminé usando:
results = Model.objects.exclude(a=true, x__lt=5).exclude(a=true, x__gt=5)
Debes usar el filter
y exclude
así
results = Model.objects.exclude(a=true).filter(x=5)
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 anterior está asignando Falso al parámetro a y el número 5 al parámetro x. No está comprobando la igualdad. Por lo tanto, realmente no hay forma de usar el símbolo! = En una llamada de consulta.
En Django 1.9 / 1.10 hay tres opciones.
results = Model.objects.exclude(a=true).filter(x=5)
Usa los objetos
Q()
y el operador~
from django.db.models import Q object_list = QuerySet.filter(~Q(a=True), x=5)
Registrar una función de búsqueda personalizada
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 agregó en Django 1.8 y permite la búsqueda personalizada como de costumbre:results = Model.objects.exclude(a=True, x__ne=5)
Es fácil crear una búsqueda personalizada con Django 1.7. Hay un ejemplo de búsqueda __ne
en la documentación oficial de Django .
Necesitas crear primero la búsqueda:
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
Entonces necesitas registrarlo:
from django.db.models.fields import Field
Field.register_lookup(NotEqual)
Y ahora puede usar la búsqueda __ne
en sus consultas de esta manera:
results = Model.objects.exclude(a=True, x__ne=5)
Lo que está buscando son todos los objetos que tienen ya sea a=false
o x=5
. En Django, |
Sirve como operador OR
entre consultas:
results = Model.objects.filter(x=5).exclude(a=true)
Mientras que con los modelos, puede filtrar con =
, __gt
, __gte
, __lt
, __lte
, no puede usar ne
__lte
!=
O <>
. Sin embargo, puede lograr un mejor filtrado al usar el objeto Q.
Puede evitar el encadenamiento de QuerySet.filter()
y QuerySet.exlude()
, y usar esto:
from django.db.models import Q
object_list = QuerySet.filter(~Q(field=''not wanted''), field=''wanted'')
Su consulta parece tener un doble negativo, quiere excluir todas las filas donde x no es 5, en otras palabras, quiere incluir todas las filas donde x es 5. Creo que esto hará el truco.
results = Model.objects.filter(x=5).exclude(a=true)
Para responder a su pregunta específica, no hay "no igual a" pero eso es probablemente porque django tiene disponibles los métodos "filtro" y "excluir", por lo que siempre puede cambiar la lógica para obtener el resultado deseado.
Tal vez los objetos Q podrían ser de ayuda para este problema. Nunca los he usado, pero parece que se pueden negar y combinar de forma muy similar a las expresiones de python normales.
Actualización: Acabo de probarlo, parece funcionar 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>, ...]
Usando excluir y filtrar
results = Model.objects.filter(a=false)|Model.objects.filter(x=5)
la sintaxis de field=value
en las consultas es una abreviatura de field__exact=value
. Es decir, Django coloca los operadores de consulta en los campos de consulta en los 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 combinando estos con los objetos Q como sugiere Dave Vogt y utilizando filter()
o exclude()
como Jason Baker sugiere que obtendrá exactamente lo que necesita para cualquier consulta posible.
Django-model-values (divulgación: autor) proporciona una implementación de la búsqueda NotEqual , 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)
results = Model.objects.filter(a = True).exclude(x = 5) Generetes este sql:
select * from tablex where a != 0 and x !=5 El SQL depende de cómo se representa su campo Verdadero / Falso y el motor de la base de datos. El código django es todo lo que necesitas.