¿Cuál es la diferencia entre el filtro con múltiples argumentos y el filtro de cadena en django?
python
django
django-models
testmobile
fuente
fuente
Respuestas:
Como puede ver en las declaraciones SQL generadas, la diferencia no es el "O" como algunos sospechan. Así es como se colocan WHERE y JOIN.
Example1 (misma tabla unida): de https://docs.djangoproject.com/en/dev/topics/db/queries/#spanning-multi-valued-relationships
Blog.objects.filter( entry__headline__contains='Lennon', entry__pub_date__year=2008)
Esto le dará todos los blogs que tienen una entrada con ambos
(entry__headline__contains='Lennon') AND (entry__pub_date__year=2008)
, que es lo que esperaría de esta consulta.Resultado:
Blog with {entry.headline: 'Life of Lennon', entry.pub_date: '2008'}
Ejemplo 2 (encadenado)
Blog.objects.filter( entry__headline__contains='Lennon' ).filter( entry__pub_date__year=2008)
Esto cubrirá todos los resultados del Ejemplo 1, pero generará un poco más de resultado. Porque primero filtra todos los blogs con
(entry__headline__contains='Lennon')
y luego desde los filtros de resultados(entry__pub_date__year=2008)
.La diferencia es que también te dará resultados como:
Un solo Blog con múltiples entradas
{entry.headline: '**Lennon**', entry.pub_date: 2000}, {entry.headline: 'Bill', entry.pub_date: **2008**}
Cuando se evaluó el primer filtro, el libro se incluye debido a la primera entrada (aunque tiene otras entradas que no coinciden). Cuando se evalúa el segundo filtro, el libro se incluye debido a la segunda entrada.
Una tabla: pero si la consulta no implica tablas unidas como el ejemplo de Yuji y DTing. El resultado es el mismo.
fuente
(entry__headline__contains='Lennon')
y luego desde los filtros de resultados(entry__pub_date__year=2008)
" Si "luego del resultado" es correcto, ¿por qué incluirá algo conentry.headline == 'Bill'
.. .¿noentry__headline__contains='Lennon'
filtraría laBill
instancia?El caso en el que los resultados de "consulta de filtro de argumentos múltiples" es diferente de "consulta de filtro encadenado", siguiente:
Ejemplo:
Considere que mi aplicación
my_company
tiene dos modelosEmployee
yDependent
. Un empleadomy_company
puede tener más de dependientes (en otras palabras, un dependiente puede ser hijo / a de un solo empleado, mientras que un empleado puede tener más de un hijo / hija).Ehh, asumiendo que, como marido-mujer, ambos no pueden trabajar en a
my_company
. Tomé el ejemplo 1: mPor lo tanto,
Employee
es un modelo de referencia que puede ser referenciado por más deDependent
ese modelo de referencia. Ahora considere el estado de relación de la siguiente manera:Ahora mi consulta es:
¿Encuentra todos los empleados que tienen un hijo / hija con marcas de distinción (digamos> = 75%) tanto en la universidad como en la escuela?
>>> Employee.objects.filter(dependent__school_mark__gte=75, ... dependent__college_mark__gte=75) [<Employee: A>]
La salida es 'A' dependiente 'a1' tiene marcas de distinción tanto en la universidad como en la escuela depende del empleado 'A'. Tenga en cuenta que 'B' no se selecciona porque ninguno de los hijos de 'B' tiene marcas de distinción tanto en la universidad como en la escuela. Álgebra relacional:
En segundo lugar, caso necesito una consulta:
¿Encontrar todos los empleados cuyos dependientes tengan marcas de distinción en la universidad y la escuela?
>>> Employee.objects.filter( ... dependent__school_mark__gte=75 ... ).filter( ... dependent__college_mark__gte=75) [<Employee: A>, <Employee: B>]
Esta vez 'B' también se seleccionó porque 'B' tiene dos hijos (¡más de uno!), Uno tiene una marca de distinción en la escuela 'b1' y el otro tiene una marca de distinción en la universidad 'b2'.
El orden del filtro no importa, también podemos escribir la consulta anterior como:
>>> Employee.objects.filter( ... dependent__college_mark__gte=75 ... ).filter( ... dependent__school_mark__gte=75) [<Employee: A>, <Employee: B>]
¡el resultado es el mismo! El álgebra relacional puede ser:
Nota siguiente:
dq1 = Dependent.objects.filter(college_mark__gte=75, school_mark__gte=75) dq2 = Dependent.objects.filter(college_mark__gte=75).filter(school_mark__gte=75)
Produce el mismo resultado:
[<Dependent: a1>]
Verifico la consulta SQL de destino generada por Django usando
print qd1.query
yprint qd2.query
ambos son iguales (Django 1.6).Pero semánticamente ambos son diferentes para mí . primero se ve como una sección simple σ [marca_escuela> = 75 Y marca_universidad> = 75] (Dependiente) y la segunda como una consulta anidada lenta: σ [marca_escuela> = 75] (σ [marca_universidad> = 75] (Dependiente)).
Si uno necesita Code @codepad
por cierto, se da en la documentación @ Abarcando relaciones de múltiples valores . Acabo de agregar un ejemplo, creo que será útil para alguien nuevo.
fuente
La mayoría de las veces, solo hay un conjunto posible de resultados para una consulta.
El uso para encadenar filtros se produce cuando se trata de m2m:
Considera esto:
# will return all Model with m2m field 1 Model.objects.filter(m2m_field=1) # will return Model with both 1 AND 2 Model.objects.filter(m2m_field=1).filter(m2m_field=2) # this will NOT work Model.objects.filter(Q(m2m_field=1) & Q(m2m_field=2))
Otros ejemplos son bienvenidos.
fuente
La diferencia de rendimiento es enorme. Pruébalo y verás.
Model.objects.filter(condition_a).filter(condition_b).filter(condition_c)
es sorprendentemente lento en comparación con
Model.objects.filter(condition_a, condition_b, condition_c)
Como se menciona en Effective Django ORM ,
fuente
Puede usar el módulo de conexión para ver las consultas SQL sin procesar para comparar. Como explica Yuji, en su mayor parte son equivalentes como se muestra aquí:
>>> from django.db import connection >>> samples1 = Unit.objects.filter(color="orange", volume=None) >>> samples2 = Unit.objects.filter(color="orange").filter(volume=None) >>> list(samples1) [] >>> list(samples2) [] >>> for q in connection.queries: ... print q['sql'] ... SELECT `samples_unit`.`id`, `samples_unit`.`color`, `samples_unit`.`volume` FROM `samples_unit` WHERE (`samples_unit`.`color` = orange AND `samples_unit`.`volume` IS NULL) SELECT `samples_unit`.`id`, `samples_unit`.`color`, `samples_unit`.`volume` FROM `samples_unit` WHERE (`samples_unit`.`color` = orange AND `samples_unit`.`volume` IS NULL) >>>
fuente
Si al final de esta página buscando la manera de construir dinámicamente un conjunto de consultas Django con varios filtros de encadenamiento, pero necesita los filtros para ser del
AND
tipo en lugar deOR
, considere el uso de objetos Q .Un ejemplo:
# First filter by type. filters = None if param in CARS: objects = app.models.Car.objects filters = Q(tire=param) elif param in PLANES: objects = app.models.Plane.objects filters = Q(wing=param) # Now filter by location. if location == 'France': filters = filters & Q(quay=location) elif location == 'England': filters = filters & Q(harbor=location) # Finally, generate the actual queryset queryset = objects.filter(filters)
fuente
Si requiere ayb entonces
si requiere a así como b entonces
Documentos oficiales: https://docs.djangoproject.com/en/dev/topics/db/queries/#spanning-multi-valued-relationships
Publicación relacionada: Encadenando múltiples filtros () en Django, ¿es esto un error?
fuente
Hay una diferencia cuando tiene una solicitud a su objeto relacionado, por ejemplo
class Book(models.Model): author = models.ForeignKey(Author) name = models.ForeignKey(Region) class Author(models.Model): name = models.ForeignKey(Region)
solicitud
Author.objects.filter(book_name='name1',book_name='name2')
devuelve el conjunto vacío
y solicitud
Author.objects.filter(book_name='name1').filter(book_name='name2')
devuelve autores que tienen libros con 'nombre1' y 'nombre2'
para obtener más detalles, consulte https://docs.djangoproject.com/en/dev/topics/db/queries/#s-spanning-multi-valued-relationships
fuente
Author.objects.filter(book_name='name1',book_name='name2')
ni siquiera es python válido, lo seríaSyntaxError: keyword argument repeated