2012-03-06 9 views
7

Tengo un modelo con una cantidad de campos clave externos, p. modelo Producto con campos 'tipo', 'nivel', 'color', 'intensidad' (solo un ejemplo genérico).Django formularios en línea y choicefields generan demasiadas consultas db

Luego tengo una página para editar todos los productos de un tipo determinado utilizando un formulario tipo con los productos como un formset en línea con la opción de agregar productos adicionales en línea usando extra=10.

Lo que encuentro muy extraño es que cada vez que presento uno de los campos de selección de clave foránea en la plantilla, Django consulta la base de datos para obtener las opciones (todo el tiempo).

Por ejemplo:

{% for form in formset %} 
    {{ form.level }} 
    {{ form.color }} 
    {{ form.intensity }} 
{% endfor %} 

Con 20 productos (y 10 formas adicionales vacío) el código anterior emite 30 select * from ... desde el nivel, el color y la intensidad total de 90 consultas (revelado mediante la barra de depuración de Django), en la que 3 debería ser suficiente Es poco probable que las opciones cambien a mediados de la solicitud, pero incluso si lo hicieran, definitivamente no quisiera que aparecieran algunas opciones recién agregadas solo en los últimos 5 formularios.

¿Hay alguna manera de optimizar mis modelos/formularios/vistas/plantillas para que la base de datos no se golpee así innecesariamente?

-

exención de responsabilidad: Soy relativamente nuevo en Django y Python y no puedo evitar pensar que debe haber una manera de abordar esta construido en alguna manera.

Respuesta

4
field_queryset = Test.objects.all()  
for form in formset: 
     form.fields['test_field'].queryset = field_queryset 

Me gusta.

+0

Nice Denis, tiene sentido, simplemente haz que todos usen el mismo objeto queryset. Te tomó 11 meses para responder con una respuesta y yo otros 8 meses para aceptarlo. Mientras tanto, se dirigió a esto guardando en caché completamente los tipos 'tipo', 'nivel', 'color', bajo la premisa de que son casi constantes que no cambiarán. Pero gracias, este es un enfoque simple que tendré en cuenta la próxima vez. – davur

+0

Esto no funciona. Los formularios se construirán con los conjuntos de consulta predeterminados antes de que pueda reemplazarlos de esta manera, por lo que hará tantas consultas. –

+1

@ Adrián, en realidad "sí y no", creo. Tiene razón, los querysets predeterminados probablemente se crearán en el constructor Form. Sin embargo, crear un conjunto de consulta no es lo mismo que consultar la base de datos. Si reemplaza el conjunto de consulta antes de que se emitan las primeras consultas, aún puede guardar todas las llamadas innecesarias a la base de datos. Debería reemplazarlos antes de mostrar el primer formulario en la plantilla y antes de llamar a 'save' en cada formulario. – davur

1

Puede change the queryset used by the formset, luego puede usar select_related() para generar las uniones FK en lugar de ejecutar una consulta en cada iteración forloop.

+1

No veo cómo esto podría ayudar en esta situación. El conjunto de preguntas es para seleccionar los valores actuales de los productos, y select_related podría ayudar a buscar los objetos de nivel/color/intensidad vinculados actualmente a cada producto. ¿Cómo ayuda select_related a la recuperación previa de todo el conjunto de opciones de selección para completar el cuadro Seleccionar? – davur

+0

Ok, así podría usar un autocompletar ajax (django-ajax-selects) o usar un caché de consulta (johnnycache). – jpic

Cuestiones relacionadas