Dada una clase:
from django.db import models
class Person(models.Model):
name = models.CharField(max_length=20)
¿Es posible, y si es así, tener un QuerySet que filtre en función de argumentos dinámicos? Por ejemplo:
# Instead of:
Person.objects.filter(name__startswith='B')
# ... and:
Person.objects.filter(name__endswith='B')
# ... is there some way, given:
filter_by = '{0}__{1}'.format('name', 'startswith')
filter_value = 'B'
# ... that you can run the equivalent of this?
Person.objects.filter(filter_by=filter_value)
# ... which will throw an exception, since `filter_by` is not
# an attribute of `Person`.
python
django
django-models
Brian M. Hunt
fuente
fuente
Un ejemplo simplificado:
En una aplicación de encuesta de Django, quería una lista de selección HTML que mostrara a los usuarios registrados. Pero debido a que tenemos 5000 usuarios registrados, necesitaba una forma de filtrar esa lista en función de los criterios de consulta (como las personas que completaron un determinado taller). Para que el elemento de la encuesta sea reutilizable, necesitaba que la persona que crea la pregunta de la encuesta pueda adjuntar esos criterios a esa pregunta (no quiero codificar la consulta en la aplicación).
La solución que se me ocurrió no es fácil de usar al 100% (requiere la ayuda de un técnico para crear la consulta), pero resuelve el problema. Al crear la pregunta, el editor puede ingresar un diccionario en un campo personalizado, por ejemplo:
Esa cadena se almacena en la base de datos. En el código de vista, vuelve como
self.question.custom_query
. El valor de eso es una cadena que se parece a un diccionario. Lo convertimos de nuevo en un diccionario real con eval () y luego lo rellenamos en el conjunto de consultas con ** kwargs:fuente
eval()
a la importación de usuarios es una mala idea, incluso si confía completamente en sus usuarios. Un campo JSON sería una mejor idea aquí.Django.db.models.Q es exactamente lo que quieres de una manera Django.
fuente
Q(**filters)
, si desea construir dinámicamente objetos Q, puede ponerlos en una lista y usarlos.filter(*q_objects)
, o usar los operadores bit a bit para combinar los objetos Q.Un formulario de búsqueda realmente complejo generalmente indica que un modelo más simple está intentando cavar.
¿Cómo, exactamente, espera obtener los valores para el nombre y la operación de la columna? ¿De dónde sacas los valores de
'name'
un'startswith'
?¿Un formulario de "búsqueda"? Vas a ... ¿qué? - elegir el nombre de una lista de nombres? Elija la operación de una lista de operaciones? Si bien son abiertas, la mayoría de las personas encuentran esto confuso y difícil de usar.
¿Cuántas columnas tienen tales filtros? 6? 12? 18?
Botones de filtro específicos. Espera ... Así es como funciona el administrador de Django. Los filtros específicos se convierten en botones. Y se aplica el mismo análisis que el anterior. Algunos filtros tienen sentido. Una gran cantidad de filtros generalmente significa una especie de primera violación de forma normal.
Muchos campos similares a menudo significan que debería haber más filas y menos campos.
fuente