2012-05-03 26 views
5

Tengo esta declaración queryset largo en una vistaRe evaluar consulta Django después de los cambios realizados a la base de datos

contributions = user_profile.contributions_chosen.all()\ 
    .filter(payed=False).filter(belongs_to=concert)\ 
    .filter(contribution_def__left__gt=0)\ 
    .filter(contribution_def__type_of='ticket') 

que yo uso en mi plantilla

context['contributions'] = contributions 

Y más tarde ese punto de vista hago cambios (agregar o quitar un registro) a la tabla contribuciones_cortas y si quiero que mi contexto ['contribuciones'] se actualice necesito volver a consultar la base de datos con la misma consulta larga.

contributions = user_profile.contributions_chosen.all()\ 
.filter(payed=False).filter(belongs_to=concert)\ 
.filter(contribution_def__left__gt=0)\ 
.filter(contribution_def__type_of='ticket') 

Y luego otra vez al día mi contexto

context['contributions'] = contributions 

así que me preguntaba si tener ninguna manera puedo evitar la repetición de mi mismo, para volver a evaluar las contribuciones de modo que en realidad refleja los datos reales de la base de datos. Idealmente, modificaría las contribuciones del conjunto de pruebas y sus valores se actualizarían, y al mismo tiempo la base de datos reflejaría estos cambios, pero no sé cómo hacerlo.

ACTUALIZACIÓN: Esto es lo que hago entre los dos contexto [ 'contribuciones'] = contribuciones

agrego un nuevo objeto contribución a la contributions_chosen (esto es una relación M2M),

contribution = Contribution.objects.create(kwarg=something,kwarg2=somethingelse) 
user_profile.contributions_chosen.add(contribution) 
contribution.save() 
user_profile.save() 

Y en algunos casos i eliminar un objeto contribución contribución = user_profile.contributions_chosen.get (id = 1) user_profile.contributions_chosen.get (id = request.POST [ 'con contribution.delete()

Como puedes ver, estoy modificando la tabla contribuciones_por ejemplo, así que tengo que volver a enviar la consulta y actualizar el contexto. ¿Qué estoy haciendo mal?

ACTUALIZACIÓN Después de ver sus comentarios acerca de la evaluación, me doy cuenta de que eval queryset hago len (contribuciones) entre el contexto [ 'contribución'] y que parece ser un problema. Lo moveré después de las operaciones de la base de datos y eso es todo, gracias chico.

+0

parece que no ha evaluado la queryset 'contributions', por lo tanto no hay necesidad de preocuparse por su actualización, ya que todavía tiene datos no obtienen de DB. 'QuerySet' se evalúa de forma diferida, por lo tanto, no tiene nada que ver con las filas de DB hasta que se haya evaluado. – okm

Respuesta

2

No sé cómo evitar la reevaluación de la consulta, pero una forma de guardar algunas afirmaciones repetidas en su código sería crear un dict con todos esos filtros y especificar filter como un dict:

query_args = dict(
    payed=False, 
    belongs_to=concert, 
    contribution_def__left__gt=0, 
    contribution_def__type_of='ticket', 
) 

y luego

contributions = user_profile.contributions_chosen.filter(**query_args) 

Esto sólo elimina algo de código repetido, pero no resuelve la consulta repetida. Si es necesario cambiar los argumentos, se encarga solamente de query_args como un diccionario normal de Python, que es una actualización después de todo :)

+1

En el código que proporciona, parece que no evalúa la consulta de todos modos. La consulta se evalúa cuando itera sobre ella en la plantilla o cuando hace otras cosas que desencadenan la evaluación de la consulta, como se documenta en https://docs.djangoproject.com/en/dev/ref/models/querysets/#when-querysets -are-evaluate –

3

parece que no has evaluado la queryset contributions, por lo tanto no hay necesidad de preocuparse actualizándolo porque todavía no ha obtenido datos de DB.

¿Se puede publicar el código entre dos líneas context['contributions'] = contributions? Normalmente, antes de evaluar el conjunto de consultas contributions (por ejemplo, al iterar sobre él o llamando a su __len__()), no contiene nada que lea de DB, por lo tanto, no tiene que actualizar su contenido .

para volver a evaluar un conjunto de consultas, podría

# make a clone 
contribution._clone() 
# or any op that makes clone, for example 
contribution.filter() 

# or clear its cache 
contribution._result_cache = None 

# you could even directly add new item to contribution._result_cache, 
# but its could cause unexpected behavior w/o carefulness 
+1

También 'contribution.all()' –

+0

Los documentos específicamente [sugieren usar 'all()'] (https://docs.djangoproject.com/en/1.11/ref/models/querysets/#all) para este propósito. –

Cuestiones relacionadas