update queryset query example python django django-models

queryset - models py python



diferencia entre filtro con argumentos múltiples y filtro de cadena en django (7)

¿Cuál es la diferencia entre filtro con múltiples argumentos y filtro de cadena en django?


Como puede ver en las sentencias SQL generadas, la diferencia no es el "OR", como algunos pueden sospechar. Es cómo se coloca WHERE y JOIN.

Ejemplo1 (la 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 le 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 incluyó 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 involucra tablas unidas como el ejemplo de Yuji y DTing. El resultado es el mismo


El caso en el que los resultados de "múltiples argumentos filtro-consulta" es diferente a "encadenado-filtro-consulta", a continuación:

La selección de objetos referenciados sobre la base de referenciar objetos y relaciones es de uno a muchos (o de muchos a muchos).

Múltiples filtros:

Referenced.filter(referencing1_a=x, referencing1_b=y) # same referencing model ^^ ^^

Filtros encadenados:

Referenced.filter(referencing1_a=x).filter(referencing1_b=y)

Ambas consultas pueden generar resultados diferentes:
Si hay más de una fila en el modelo de Referencing1 , Referencing1 puede hacer referencia a la misma fila en el modelo Referenced que se hace Referenced . Este puede ser el caso en Referenced : Referencing1 tiene relación de 1: N (de uno a muchos) o de N: M (de muchos a muchos).

Ejemplo:

Considere mi aplicación my_company tiene dos modelos Employee y Dependent . Un empleado de my_company puede tener más que dependientes (en otras palabras, un dependiente puede ser hijo / hija de un solo empleado, mientras que un empleado puede tener más de un hijo / hija).
Ehh, asumiendo que esposo y esposa no pueden trabajar en my_company . Tomé el ejemplo 1: m

Por lo tanto, se hace referencia al Employee : modelo al que se puede hacer referencia en más de un Dependent que hace referencia al modelo. Ahora considere relación-estado de la siguiente manera:

Employee: Dependent: +------+ +------+--------+-------------+--------------+ | name | | name | E-name | school_mark | college_mark | +------+ +------+--------+-------------+--------------+ | A | | a1 | A | 79 | 81 | | B | | b1 | B | 80 | 60 | +------+ | b2 | B | 68 | 86 | +------+--------+-------------+--------------+

El dependiente a1 refiere al empleado A y las referencias dependientes b1, b2 al empleado B

Ahora mi consulta es:

Buscar todos los empleados que tienen hijo / hija tiene 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 en la universidad y la escuela depende del empleado ''A''. La nota ''B'' no está seleccionada porque el hijo menor de ''B'' tiene marcas de distinción tanto en la universidad como en la escuela. Álgebra relacional:

Empleado (school_mark> = 75 AND college_mark> = 75) Dependiente

En Segundo caso, necesito una consulta:

¿Encuentra a todos los empleados cuyas personas a su cargo tienen marcas distintivas 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 otro tiene una marca de distinción en la universidad ''b2''.
El orden de 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>]

resultado es lo mismo! El álgebra relacional puede ser:

(Empleado (school_mark> = 75) Dependiente) (college_mark> = 75) Dependiente

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)

Resultados del mismo resultado: [<Dependent: a1>]

Compruebo la consulta SQL de destino generada por Django utilizando print qd1.query e print qd2.query son los mismos (Django 1.6).

Pero, semánticamente, ambos son diferentes a . primero se ve como la sección simple σ [marca_escuela> = 75 Y marca_de_universidad> = 75] (Dependiente) y la segunda como consulta anidada lenta: σ [marca_escuela> = 75][marca_de_agricultura> = 75] (Dependiente)).

Si necesitas Code @codepad

Por cierto, se presenta en la documentación @ https://docs.djangoproject.com/en/dev/topics/db/queries/#spanning-multi-valued-relationships Acabo de agregar un ejemplo, creo que será útil para alguien nuevo.


Hay una diferencia cuando tiene una solicitud para 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 un 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 más información, consulte https://docs.djangoproject.com/en/dev/topics/db/queries/#s-spanning-multi-valued-relationships


La diferencia de rendimiento es enorme. Pruébalo y mira.

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" ,

  • QuerySets mantiene el estado en la memoria
  • El encadenamiento desencadena la clonación, duplicando ese estado
  • Desafortunadamente, QuerySets mantiene un montón de estado
  • Si es posible, no encadene más de un filtro

La mayoría de las veces, solo hay un posible conjunto de resultados para una consulta.

El uso de filtros de encadenamiento 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.


Puede usar el módulo de conexión para ver las consultas en sql sin procesar para comparar. Como explicó Yuji''s, 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) >>>


Si termina en esta página buscando cómo construir dinámicamente un queryset django con múltiples filtros de encadenamiento, pero necesita que los filtros sean del tipo AND lugar de OR , considere usar 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)