Foros del Web » Programando para Internet » Python »

Campos opcionales con UserChangeForm

Estas en el tema de Campos opcionales con UserChangeForm en el foro de Python en Foros del Web. Hola a todos Tengo un modelo de usuarios extendido mediante 'AbstractUser': models.py @import url("http://static.forosdelweb.com/clientscript/vbulletin_css/geshi.css"); Código Python: Ver original from django. db import models from django. ...
  #1 (permalink)  
Antiguo 24/12/2014, 09:21
Avatar de kojicomics  
Fecha de Ingreso: junio-2013
Mensajes: 49
Antigüedad: 11 años, 6 meses
Puntos: 1
Campos opcionales con UserChangeForm

Hola a todos

Tengo un modelo de usuarios extendido mediante 'AbstractUser':

models.py
Código Python:
Ver original
  1. from django.db import models
  2. from django.contrib.auth.models import AbstractUser
  3.  
  4.  
  5. class Profiles(AbstractUser):
  6.     url = models.URLField()
  7.     avatar = models.ImageField(upload_to='profile_avatar')

Tengo también un formulario para modificar los usuarios basado en 'UserChangeForm':

forms.py
Código Python:
Ver original
  1. from django import forms
  2. from django.contrib.auth.forms import UserChangeForm
  3. from django.utils.translation import ugettext as _
  4. from .models import Profiles
  5.  
  6.  
  7. class UserEditForm(UserChangeForm):
  8.  
  9.     class Meta:
  10.         model = Profiles
  11.         fields = ('username', 'first_name', 'last_name', 'email', 'url',
  12.                   'avatar',)
  13.         exclude = ('password',)
  14.  
  15.     def clean_username(self):
  16.         username = self.cleaned_data['username']
  17.         try:
  18.             Profiles.objects.get(username=username)
  19.         except Profiles.DoesNotExist:
  20.             return username
  21.         raise forms.ValidationError(_('Duplicate username'))
  22.  
  23.     def clean_avatar(self):
  24.         avatar = self.cleaned_data['avatar']
  25.         if avatar:
  26.             if avatar._size > 1024 * 1024:
  27.                 raise forms.ValidationError(_('Image file too large ( > 1mb )'))
  28.             return avatar
  29.         else:
  30.             raise forms.ValidationError(_("Couldn't read uploaded image"))
  31.  
  32.     def clean_password(self):
  33.         return ""

El formulario lo ejecuto mediante esta vista:

views.py
Código Python:
Ver original
  1. from django.views.generic import UpdateView
  2. from .models import Profiles
  3. from .forms import UserEditForm
  4.  
  5.  
  6. class UserEdit(UpdateView):
  7.     model = Profiles
  8.     form_class = UserEditForm
  9.     success_url = reverse_lazy('profile')
  10.     template_name = 'profile/edit.html'
  11.  
  12.     def get_object(self, queryset=None):
  13.         return self.request.user

El formulario de modificación funciona correctamente en la aplicación, pero tengo dos problemas:

El primero es que el formulario requiere que el usuario inserte obligatoriamente los campos adicionales (los de mi modelo extendido) para poder enviar el formulario.

Lo he solucionado redefiniendo los campos dentro del formulario junto con el atributo "required=False" pero me gustaría saber si hay algún método de aplicar ésto a todos los campos sin tener que modificarlos uno a uno.

El segundo problema, y el más importante, es que los campos que el usuario no rellene en el formulario, en vez de ignorarlos, elimina su valor anterior.

Una posible solución es generar el valor de las etiquetas dinámicamente mediante:
Código:
value={{user.fieldname}}
Pero en caso de eliminar el valor de un campo volveríamos al mismo problema.

Un saludo, Gracias
  #2 (permalink)  
Antiguo 24/12/2014, 10:45
Avatar de razpeitia
Moderador
 
Fecha de Ingreso: marzo-2005
Ubicación: Monterrey, México
Mensajes: 7.321
Antigüedad: 19 años, 9 meses
Puntos: 1360
Respuesta: Campos opcionales con UserChangeForm

En tu modelo pones en los campos que quieres que sean opcionales blank=True.

No ocupas checar que el username sea único, en el modelo base, username es un indice único y ademas ese tipo de validaciones se hace a nivel instancia, no a nivel campo.
  #3 (permalink)  
Antiguo 25/12/2014, 17:09
Avatar de kojicomics  
Fecha de Ingreso: junio-2013
Mensajes: 49
Antigüedad: 11 años, 6 meses
Puntos: 1
Respuesta: Campos opcionales con UserChangeForm

Cita:
Iniciado por razpeitia Ver Mensaje
En tu modelo pones en los campos que quieres que sean opcionales blank=True.
El problema de especificar si son opcionales o no en el modelos, es que por ejemplo me interesa que el email sea obligatorio en el formulario de registro pero opcional en el formulario de modificación.

Cita:
Iniciado por razpeitia Ver Mensaje
No ocupas checar que el username sea único, en el modelo base, username es un indice único y ademas ese tipo de validaciones se hace a nivel instancia, no a nivel campo.
Probé a validar los datos a nivel de instancia pero no muestra el mensaje de error en el template, mientras que al validar desde el formulario sí lo hace.

Éste es un ejemplo:
Código Python:
Ver original
  1. class Profiles(AbstractUser):
  2.     avatar = models.ImageField(upload_to='profile_avatar', blank=True)
  3.  
  4.     def clean(self):
  5.         avatar = self.avatar
  6.         if avatar.file.size > 1024*1024:
  7.             raise ValidationError(_('Image file too large ( > 1mb )'))

También probé con forms.ValidationError pero tampoco muestra nada

De todas formas, como dije en el post, mi principal duda es cómo evitar que si un usuario deja en blanco un campo al modificar su perfil, éste se actualice con el valor vacío, en vez de conservar el anterior

Un saludo
  #4 (permalink)  
Antiguo 25/12/2014, 17:30
Avatar de razpeitia
Moderador
 
Fecha de Ingreso: marzo-2005
Ubicación: Monterrey, México
Mensajes: 7.321
Antigüedad: 19 años, 9 meses
Puntos: 1360
Respuesta: Campos opcionales con UserChangeForm

Cita:
Iniciado por kojicomics Ver Mensaje
El problema de especificar si son opcionales o no en el modelos, es que por ejemplo me interesa que el email sea obligatorio en el formulario de registro pero opcional en el formulario de modificación.
Eso no tiene sentido. Imagina que me registro con un email y luego al actualizarlo lo quito. No habría diferencia hay si lo tuvieras opcional desde el inicio.

Cita:
Iniciado por kojicomics Ver Mensaje
Probé a validar los datos a nivel de instancia pero no muestra el mensaje de error en el template, mientras que al validar desde el formulario sí lo hace.
Que no muestre el error es porque simplemente no lo muestras, no se como estés renderizando el formulario. Pero estoy seguro que no estas mostrando los forms.non_field_errors.
  #5 (permalink)  
Antiguo 26/12/2014, 07:37
Avatar de kojicomics  
Fecha de Ingreso: junio-2013
Mensajes: 49
Antigüedad: 11 años, 6 meses
Puntos: 1
Respuesta: Campos opcionales con UserChangeForm

Al final he conseguido solucionar el problema de los valores en blanco. Compruebo el tamaño del valor, de forma que si es igual a 0, utiliza el valor anterior

forms.py

Código Python:
Ver original
  1. class UserEditForm(UserChangeForm):
  2.  
  3.     class Meta:
  4.         model = Profiles
  5.         fields = ('username', 'first_name', 'last_name', 'email', 'url',
  6.                   'avatar',)
  7.         exclude = ('password',)
  8.  
  9.     def __init__(self, user, *args, **kwargs):
  10.         super(UserEditForm, self).__init__(*args, **kwargs)
  11.         self.user = user
  12.  
  13.     def clean(self):
  14.         cleaned_data = self.cleaned_data
  15.         for field, value in list(cleaned_data.items()):
  16.             old_value = getattr(self.user, field)
  17.             if len(value) > 0:
  18.                 cleaned_data[field] = value
  19.             else:
  20.                 cleaned_data[field] = old_value
  21.  
  22.         return cleaned_data
  23.  
  24.     def clean_password(self):
  25.         return ""

views.py

Código Python:
Ver original
  1. class UserEdit(UpdateView):
  2.     model = Profiles
  3.     form_class = UserEditForm
  4.     success_url = reverse_lazy('profile')
  5.     template_name = 'profile/edit.html'
  6.  
  7.     def get_form_kwargs(self):
  8.         kwargs = super(UserEdit, self).get_form_kwargs()
  9.         kwargs['user'] = self.request.user
  10.         return kwargs
  11.  
  12.     def get_object(self, queryset=None):
  13.         return self.request.user

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 07:26.