Foros del Web » Programando para Internet » Python »

¿Cómo tratar varios artículos a la vez en Django?

Estas en el tema de ¿Cómo tratar varios artículos a la vez en Django? en el foro de Python en Foros del Web. Hola, Tengo una vista con la que saco los artículo ( Lista.objects.all() ) del modelo Lista. Ese modelo Lista tiene los campos: usuario => ForeignKey(User) ...
  #1 (permalink)  
Antiguo 01/11/2012, 04:35
 
Fecha de Ingreso: septiembre-2010
Mensajes: 28
Antigüedad: 14 años, 2 meses
Puntos: 0
Pregunta ¿Cómo tratar varios artículos a la vez en Django?

Hola,

Tengo una vista con la que saco los artículo ( Lista.objects.all() ) del modelo Lista. Ese modelo Lista tiene los campos:
  • usuario => ForeignKey(User)
  • articulo => ForeignKey(Articulo)
  • unidades
La lista de artículos me queda así, pongo imagen:



Las unidades salen así porque las metí en un input en la plantilla. Y el botón de "Actualizar unidades" también es otro input que metí yo en la plantilla. Lo mismo con el botoncito del carrito, que sería para eliminar el artículo.

Ahora bien, mis dos consultas:

¿alguien podría orientarme cómo tendría que hacer para que funcione el poder actualizar las unidades que el usuario cambie en los input?
¿alguien podría orientarme cómo tendría que hacer para que el usuario pueda borrar las unidades dándole al botoncito del carrito?

¡Saludos y gracias de antemano!
  #2 (permalink)  
Antiguo 01/11/2012, 10:25
Avatar de Carlangueitor
Moderador ლ(ಠ益ಠლ)
 
Fecha de Ingreso: marzo-2008
Ubicación: México
Mensajes: 10.037
Antigüedad: 16 años, 8 meses
Puntos: 1329
Respuesta: ¿Cómo tratar varios artículos a la vez en Django?

Ya te lo comentaron en la lista de Django-es Tienes que usar formsets: https://docs.djangoproject.com/en/de...orms/formsets/

Saludos
__________________
Grupo Telegram Docker en Español
  #3 (permalink)  
Antiguo 01/11/2012, 10:38
Avatar de razpeitia
Moderador
 
Fecha de Ingreso: marzo-2005
Ubicación: Monterrey, México
Mensajes: 7.321
Antigüedad: 19 años, 8 meses
Puntos: 1360
Respuesta: ¿Cómo tratar varios artículos a la vez en Django?

A pesar de que te hayan respondido en la lista de correos, puedes hacer la operación a mano (desde la lista).

Por ejemplo actualizar artículos, seria una petición POST a esa misma (o diferente) URL, donde esperas ciertos parámetros, como las unidades, el usuario y los artículos.

Y para eliminar un articulo, puedes hacer una petición GET a otra URL, igual esperando parámetros como usuario y articulo y después redirigir a tu URL de artículos.
  #4 (permalink)  
Antiguo 01/11/2012, 13:36
 
Fecha de Ingreso: septiembre-2010
Mensajes: 28
Antigüedad: 14 años, 2 meses
Puntos: 0
Respuesta: ¿Cómo tratar varios artículos a la vez en Django?

Cita:
Iniciado por Carlangueitor Ver Mensaje
Ya te lo comentaron en la lista de Django-es Tienes que usar formsets: [url]https://docs.djangoproject.com/en/dev/topics/forms/formsets/[/url]

Saludos
Ya estuve probando con los formsets y no fui capaz, por eso pido ayudo en otros sitios. Pero gracias igual. :)


Cita:
Iniciado por razpeitia Ver Mensaje
A pesar de que te hayan respondido en la lista de correos, puedes hacer la operación a mano (desde la lista).

Por ejemplo actualizar artículos, seria una petición POST a esa misma (o diferente) URL, donde esperas ciertos parámetros, como las unidades, el usuario y los artículos.

Y para eliminar un articulo, puedes hacer una petición GET a otra URL, igual esperando parámetros como usuario y articulo y después redirigir a tu URL de artículos.
¿Podría ponerme algún ejemplo práctico por favor? Soy bastante nuevo en Django, a penas llevo un mes y todavía me cuesta un poco.

¡Gracias de antemano!
  #5 (permalink)  
Antiguo 01/11/2012, 13:42
Avatar de Carlangueitor
Moderador ლ(ಠ益ಠლ)
 
Fecha de Ingreso: marzo-2008
Ubicación: México
Mensajes: 10.037
Antigüedad: 16 años, 8 meses
Puntos: 1329
Respuesta: ¿Cómo tratar varios artículos a la vez en Django?

¿Cómo vamos a poder decirte en que estás mal si no pones lo que ya probaste?
__________________
Grupo Telegram Docker en Español
  #6 (permalink)  
Antiguo 01/11/2012, 14:07
Avatar de razpeitia
Moderador
 
Fecha de Ingreso: marzo-2005
Ubicación: Monterrey, México
Mensajes: 7.321
Antigüedad: 19 años, 8 meses
Puntos: 1360
Respuesta: ¿Cómo tratar varios artículos a la vez en Django?

Cita:
Iniciado por Carlangueitor Ver Mensaje
¿Cómo vamos a poder decirte en que estás mal si no pones lo que ya probaste?
Tal como dice Carlangueitor no podemos proveerte ningún ejemplo basado en la poca (casi nula) información que nos das.

Te podemos proporcionar un ejemplo muy general, pero te quedarías igual que en la explicación.
  #7 (permalink)  
Antiguo 02/11/2012, 08:03
 
Fecha de Ingreso: septiembre-2010
Mensajes: 28
Antigüedad: 14 años, 2 meses
Puntos: 0
Respuesta: ¿Cómo tratar varios artículos a la vez en Django?

Entiendo... Os dejo más información de lo que yo hice leyendo la documentación de Django. Tras poner todo eso lo único que me sale en la página es el botón de Actualizar unidades.

Por sino se sobreentiende, lo que estoy tratando de hacer es un carrito de compra, donde los artículos son los recambios.

Saludos y gracias de antemano de nuevo.

models.py
Código Python:
Ver original
  1. class CarritoDeCompra(models.Model):
  2.     user = models.ForeignKey(User)
  3.     recambio = models.ForeignKey(Recambio)
  4.     unidades = models.PositiveSmallIntegerField()
  5.     precio = models.FloatField()
  6.     subfamilia = models.ForeignKey(Subfamilia)
  7.  
  8.     class Meta:
  9.         verbose_name_plural = 'Carritos de compra'
  10.  
  11.     def __unicode__(self):
  12.         return unicode(self.user)
forms.py
Código Python:
Ver original
  1. class UnidadesForm(forms.ModelForm):
  2.     class Meta:
  3.         model = CarritoDeCompra
  4.         fields = ['unidades']
views.py
Código Python:
Ver original
  1. @login_required(login_url='/iniciar-sesion/')
  2. def carrito_de_compra(request):
  3.     lista_recambios = CarritoDeCompra.objects.filter(user=request.user)
  4.  
  5.     precio_total = 0
  6.     unidades_totales = 0
  7.     for recambio in lista_recambios:
  8.         precio_total = recambio.precio * recambio.unidades + precio_total
  9.         unidades_totales = recambio.unidades + unidades_totales
  10.  
  11.  
  12.     UnidadesFormSet = formset_factory(CarritoDeCompra, extra=0)
  13.     if request.method == 'POST':
  14.         formset = UnidadesFormSet(request.POST, request.FILES)
  15.         if formset.is_valid():
  16.             # actualizar las unidades
  17.             return HttpResponseRedirect('/carrito-de-compra/')
  18.     else:
  19.         formset = UnidadesFormSet()
  20.  
  21.  
  22.     return render_to_response('carrito_de_compra.html', {
  23.         'lista_recambios': lista_recambios,
  24.         'precio_total': precio_total,
  25.         'unidades_totales': unidades_totales,
  26.         'formset': formset
  27.     }, context_instance=RequestContext(request))
carrito_de_compra.html
Código Python:
Ver original
  1. [...]
  2. <form method="post" action="">{% csrf_token %}
  3.     {{ formset.management_form }}
  4.     <table>
  5.         {% for form in formset %}
  6.             {{ form }}
  7.         {% endfor %}
  8.     </table>
  9.     <input type="submit" value="Actualizar unidades"/>
  10. </form>
  11. [...]
  #8 (permalink)  
Antiguo 04/11/2012, 07:09
 
Fecha de Ingreso: septiembre-2010
Mensajes: 28
Antigüedad: 14 años, 2 meses
Puntos: 0
Respuesta: ¿Cómo tratar varios artículos a la vez en Django?

Perdonen el doble post, pero si necesitan alguna información más no duden en pedírmela.

¡Gracias!
  #9 (permalink)  
Antiguo 04/11/2012, 18:52
Avatar de razpeitia
Moderador
 
Fecha de Ingreso: marzo-2005
Ubicación: Monterrey, México
Mensajes: 7.321
Antigüedad: 19 años, 8 meses
Puntos: 1360
Respuesta: ¿Cómo tratar varios artículos a la vez en Django?

Código Python:
Ver original
  1. @login_required(login_url='/iniciar-sesion/')
  2. def carrito_de_compra(request, deleted_item=None):
  3.     """deleted_item es la clave primaria (pk) del articulo a borrar,
  4.       si deleted_item es None entonces regresa el formset de lo
  5.       contrario el borrado es ejecutado."""
  6.     lista_recambios = CarritoDeCompra.objects.filter(user=request.user)
  7.  
  8.     precio_total = 0
  9.     unidades_totales = 0
  10.     for recambio in lista_recambios:
  11.         precio_total = recambio.precio * recambio.unidades + precio_total
  12.         unidades_totales = recambio.unidades + unidades_totales
  13.  
  14.  
  15.     UnidadesFormSet = formset_factory(CarritoDeCompra, extra=0)
  16.     if request.method == 'POST':
  17.         formset = UnidadesFormSet(request.POST, request.FILES)
  18.         if formset.is_valid():
  19.             # actualizar las unidades
  20.             formset.save()
  21.             return HttpResponseRedirect('/carrito-de-compra/')
  22.     else:
  23.         if deleted_item:
  24.             item_to_erase = lista_recambios.get(pk=deleted_item)
  25.             item_to_erase.delete()
  26.             item_to_erase = None
  27.             return HttpResponseRedirect('/carrito-de-compra/')
  28.         else:
  29.             formset = UnidadesFormSet()
  30.  
  31.  
  32.     return render_to_response('carrito_de_compra.html', {
  33.         'lista_recambios': lista_recambios,
  34.         'precio_total': precio_total,
  35.         'unidades_totales': unidades_totales,
  36.         'formset': formset
  37.     }, context_instance=RequestContext(request))
No tengo todo el proyecto como para hacer pruebas, pero al menos esto te servirá.
  #10 (permalink)  
Antiguo 05/11/2012, 17:57
 
Fecha de Ingreso: septiembre-2010
Mensajes: 28
Antigüedad: 14 años, 2 meses
Puntos: 0
Respuesta: ¿Cómo tratar varios artículos a la vez en Django?

¡Muchas gracias razpeitia!

Y tendría que crear una URL como está, ¿no?

Código Python:
Ver original
  1. urlpatterns = patterns('principal.views',
  2.     url(r'^carrito-de-compra/borrar/(?P<deleted_item>\d+)/$', 'carrito_de_compra', name='carrito_de_compra_deleted_item'),
  3. )

Al margen de eso, lo único que me sale en la página sigue siendo el botón de "Actualizar unidades".

Y la otra cosa... Yo puse "# actualizar las unidades" porque no sé cómo hacer para actualizar. ¿Cómo tendría que hacer esa parte?

Sino te es molestia y te es más cómodo a ti, podría pasarte el proyecto por si quieres comprobar algo más.

¡Saludos y gracias de nuevo, de verdad!
  #11 (permalink)  
Antiguo 05/11/2012, 18:02
Avatar de razpeitia
Moderador
 
Fecha de Ingreso: marzo-2005
Ubicación: Monterrey, México
Mensajes: 7.321
Antigüedad: 19 años, 8 meses
Puntos: 1360
Respuesta: ¿Cómo tratar varios artículos a la vez en Django?

Cita:
Iniciado por abdonroda Ver Mensaje
¡Muchas gracias razpeitia!
De nada

Cita:
Iniciado por abdonroda Ver Mensaje
Y tendría que crear una URL como está, ¿no?

Código Python:
Ver original
  1. urlpatterns = patterns('principal.views',
  2.     url(r'^carrito-de-compra/borrar/(?P<deleted_item>\d+)/$', 'carrito_de_compra', name='carrito_de_compra_deleted_item'),
  3. )
Si mas o menos esa es la idea.

Cita:
Iniciado por abdonroda Ver Mensaje
Al margen de eso, lo único que me sale en la página sigue siendo el botón de "Actualizar unidades".
¿? Ok, no entendí esta parte.

Cita:
Iniciado por abdonroda Ver Mensaje
Y la otra cosa... Yo puse "# actualizar las unidades" porque no sé cómo hacer para actualizar. ¿Cómo tendría que hacer esa parte?
Yo puse abajo de ese comentario como hacerlo.

Cita:
Iniciado por abdonroda Ver Mensaje
Sino te es molestia y te es más cómodo a ti, podría pasarte el proyecto por si quieres comprobar algo más.
Claro, si lo puedes abrir a la comunidad sería genial!

Cita:
Iniciado por abdonroda Ver Mensaje
¡Saludos y gracias de nuevo, de verdad!
Saludos y de nuevo de nada.
  #12 (permalink)  
Antiguo 09/11/2012, 06:27
 
Fecha de Ingreso: septiembre-2010
Mensajes: 28
Antigüedad: 14 años, 2 meses
Puntos: 0
Respuesta: ¿Cómo tratar varios artículos a la vez en Django?

¡Gracias de nuevo!

Cita:
Iniciado por razpeitia Ver Mensaje
Cita:
Iniciado por abdonroda Ver Mensaje
Al margen de eso, lo único que me sale en la página sigue siendo el botón de "Actualizar unidades".
¿? Ok, no entendí esta parte.
Quiero decir que en vez de salir la lista de los recambios (cada uno con su input de unidades) y el botón de 'Actualizar unidades' debajo, solamente sale el botón.
  #13 (permalink)  
Antiguo 12/11/2012, 16:51
 
Fecha de Ingreso: septiembre-2010
Mensajes: 28
Antigüedad: 14 años, 2 meses
Puntos: 0
Respuesta: ¿Cómo tratar varios artículos a la vez en Django?

Adjunto imágenes de cómo se ve de forma básica. Así tengo la lista de recambios:




Y así el carrito de compra:



Y por último adjunto el proyecto entero para descargar: http://nentab.com/archivo/articulos.zip

¡Saludos y gracias de antemano!
  #14 (permalink)  
Antiguo 12/11/2012, 22:52
Avatar de razpeitia
Moderador
 
Fecha de Ingreso: marzo-2005
Ubicación: Monterrey, México
Mensajes: 7.321
Antigüedad: 19 años, 8 meses
Puntos: 1360
Respuesta: ¿Cómo tratar varios artículos a la vez en Django?

https://github.com/razpeitia/fdw-car...mpras-response
  #15 (permalink)  
Antiguo 13/11/2012, 09:38
 
Fecha de Ingreso: septiembre-2010
Mensajes: 28
Antigüedad: 14 años, 2 meses
Puntos: 0
Respuesta: ¿Cómo tratar varios artículos a la vez en Django?

Cita:
Iniciado por razpeitia Ver Mensaje
[URL="https://github.com/razpeitia/fdw-carrito-de-compras-response"]https://github.com/razpeitia/fdw-carrito-de-compras-response[/URL]
Muchísimas gracias razpeitia, me estás ayudando mucho.


Mis preguntas referentes a plantillas:

¿'{{formset.management_form}}' qué es? ¿qué hace?

¿Por qué donde está puesto '{{recambio.recambio.value}} {{recambio.recambio.as_hidden}}' sale el ID del recambio en vez del nombre? He probado con '{{recambio.recambio.nombre.value}} {{recambio.recambio.nombre.as_hidden}}', pero así no sale nada.

¿Por qué repites los cambios añadiendo 'as_hidden'? ¿Porque esos campos no van a ser editados?

¿Por qué usas '{{recambio.fields.id.initial}}' en vez de '{{recambio.id.value}}'? Nunca había usado esa manera que usaste.

¿Por qué añades '{{recambio.id}}'? Si además no sale "impresa" la id en la página.


Otras preguntas:

Si en el input de las unidades se introduce algún carácter no numérico, no valida los valores introducidos como otras veces que he hecho formularios. ¿Cómo he de hacer para que sí lo valide y me salga el mensajito "Introduce un número entero"?
  #16 (permalink)  
Antiguo 13/11/2012, 13:17
Avatar de razpeitia
Moderador
 
Fecha de Ingreso: marzo-2005
Ubicación: Monterrey, México
Mensajes: 7.321
Antigüedad: 19 años, 8 meses
Puntos: 1360
Respuesta: ¿Cómo tratar varios artículos a la vez en Django?

Cita:
Iniciado por abdonroda Ver Mensaje
Muchísimas gracias razpeitia, me estás ayudando mucho.
De nada.


Cita:
Iniciado por abdonroda Ver Mensaje
¿'{{formset.management_form}}' qué es? ¿qué hace?
Documentación

Cita:
Iniciado por abdonroda Ver Mensaje
¿Por qué donde está puesto '{{recambio.recambio.value}} {{recambio.recambio.as_hidden}}' sale el ID del recambio en vez del nombre? He probado con '{{recambio.recambio.nombre.value}} {{recambio.recambio.nombre.as_hidden}}', pero así no sale nada.
Cuando iteras el formset, lo que haces es que cada iteración es un form, recambio es un muy mal nombre para esa variable. Uso recambio.recambio.value para que solo me devuelva el valor (nada de editar este valor) y uso as_hidden por que al hacer el post request es necesario que vayan todos los valores. (Ver respuesta de arriba).

Cita:
Iniciado por abdonroda Ver Mensaje
¿Por qué repites los cambios añadiendo 'as_hidden'? ¿Porque esos campos no van a ser editados?
Exacto. De hecho en primera imagen que pusiste lo único editable que pusiste fue las unidades. Otra cosa es que te recomiendo es que no confíes en lo que regresa en campo precio (en el post request), recuerda siempre hacer el calculo según las unidades.

Cita:
Iniciado por abdonroda Ver Mensaje
¿Por qué usas '{{recambio.fields.id.initial}}' en vez de '{{recambio.id.value}}'? Nunca había usado esa manera que usaste.
¿Haz intentado con recamio.id.value?

Cita:
Iniciado por abdonroda Ver Mensaje
¿Por qué añades '{{recambio.id}}'? Si además no sale "impresa" la id en la página.
Por default form.id es el id del form y no del objeto en si. Ademas sale impresa como un hidden input.


Cita:
Iniciado por abdonroda Ver Mensaje
Si en el input de las unidades se introduce algún carácter no numérico, no valida los valores introducidos como otras veces que he hecho formularios. ¿Cómo he de hacer para que sí lo valide y me salga el mensajito "Introduce un número entero"?
Para eso puedes usar el método is_valid y capturar las excepciones de validación que puedan surgir por si falta algún otro campo.

Por ultimo para desplegar que hubo un o varios errores puedes añadir al response una variable que sea una lista de errores, si esta vacía no hay errores si hay entonces desplegar los errores.
  #17 (permalink)  
Antiguo 13/11/2012, 14:11
 
Fecha de Ingreso: septiembre-2010
Mensajes: 28
Antigüedad: 14 años, 2 meses
Puntos: 0
Respuesta: ¿Cómo tratar varios artículos a la vez en Django?

Cita:
Iniciado por razpeitia Ver Mensaje
Cuando iteras el formset, lo que haces es que cada iteración es un form, recambio es un muy mal nombre para esa variable. Uso recambio.recambio.value para que solo me devuelva el valor (nada de editar este valor) y uso as_hidden por que al hacer el post request es necesario que vayan todos los valores. (Ver respuesta de arriba).
Pero es que lo que devuelve es la id (1) del recambio, y no el nombre (Recambio de prueba).


Cita:
Iniciado por razpeitia Ver Mensaje
Exacto. De hecho en primera imagen que pusiste lo único editable que pusiste fue las unidades. Otra cosa es que te recomiendo es que no confíes en lo que regresa en campo precio (en el post request), recuerda siempre hacer el calculo según las unidades.
La primera imagen no usaba ningún formset, solo estaba maquetando cómo quedará al final.
¿Cómo? ¿Dices de poner este trozo de código dentro del 'if request.method == 'POST':'?

Código Python:
Ver original
  1. precio_total = 0
  2. unidades_totales = 0
  3. for recambio in carrito_de_compra:
  4.     precio_total = recambio.precio * recambio.unidades + precio_total
  5.     unidades_totales = recambio.unidades + unidades_totales

Cita:
Iniciado por razpeitia Ver Mensaje
¿Haz intentado con recamio.id.value?
Sí, y me da el mismo resultado, por eso te preguntaba.


Cita:
Iniciado por razpeitia Ver Mensaje
Para eso puedes usar el método is_valid y capturar las excepciones de validación que puedan surgir por si falta algún otro campo.

Por ultimo para desplegar que hubo un o varios errores puedes añadir al response una variable que sea una lista de errores, si esta vacía no hay errores si hay entonces desplegar los errores.
Lo he conseguido hacer esta tarde pero de una manera mucho más sencilla (no sé si menos eficaz); añadí el errors en la plantilla.


EDITADO:

Me acabo de encontrar con un problema... Si yo con el inspector de Chrome cambio los valores de los input hidden (precio por ejemplo) y le doy al botón de Actualizar unidades, me cambia el precio. Cosa que evidentemente no quiero que se pueda. :/
¿No puedo poner solamente un input para unidades?

Última edición por abdonroda; 13/11/2012 a las 15:54 Razón: Añadir una duda
  #18 (permalink)  
Antiguo 13/11/2012, 16:43
Avatar de razpeitia
Moderador
 
Fecha de Ingreso: marzo-2005
Ubicación: Monterrey, México
Mensajes: 7.321
Antigüedad: 19 años, 8 meses
Puntos: 1360
Respuesta: ¿Cómo tratar varios artículos a la vez en Django?

Cita:
Iniciado por abdonroda Ver Mensaje
Me acabo de encontrar con un problema... Si yo con el inspector de Chrome cambio los valores de los input hidden (precio por ejemplo) y le doy al botón de Actualizar unidades, me cambia el precio. Cosa que evidentemente no quiero que se pueda. :/
¿No puedo poner solamente un input para unidades?
Como te dije antes no confíes en el input. Lo que puedes hacer es validar, ignorar el campo precio y volver a calcular el precio en base a las unidades.
  #19 (permalink)  
Antiguo 13/11/2012, 16:45
 
Fecha de Ingreso: septiembre-2010
Mensajes: 28
Antigüedad: 14 años, 2 meses
Puntos: 0
Respuesta: ¿Cómo tratar varios artículos a la vez en Django?

Cita:
Iniciado por razpeitia Ver Mensaje
Como te dije antes no confíes en el input. Lo que puedes hacer es validar, ignorar el campo precio y volver a calcular el precio en base a las unidades.
¿Y no habría manera de hacerlo sin tener los hidden inputs? Para evitar problemas de que los puedan editar.

Última edición por abdonroda; 13/11/2012 a las 16:52
  #20 (permalink)  
Antiguo 13/11/2012, 18:12
Avatar de razpeitia
Moderador
 
Fecha de Ingreso: marzo-2005
Ubicación: Monterrey, México
Mensajes: 7.321
Antigüedad: 19 años, 8 meses
Puntos: 1360
Respuesta: ¿Cómo tratar varios artículos a la vez en Django?

Claro que si, pero tendrías que hacer tus formularios a mano.
  #21 (permalink)  
Antiguo 13/11/2012, 18:23
 
Fecha de Ingreso: septiembre-2010
Mensajes: 28
Antigüedad: 14 años, 2 meses
Puntos: 0
Respuesta: ¿Cómo tratar varios artículos a la vez en Django?

Cita:
Iniciado por razpeitia Ver Mensaje
Claro que si, pero tendrías que hacer tus formularios a mano.
¿Te refieres a esto? ¿O es más complejo?

Código Python:
Ver original
  1. class UnidadesForm(forms.ModelForm):
  2.     class Meta:
  3.         model = CarritoDeCompra
  4.         fields = ['unidades']

¿Podrías orientarme? Gracias de antemano.

Etiquetas: django
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 09:18.