Django-Registration y Django-Profile, utilizando su propio formulario personalizado

Estoy haciendo uso de django-registration y django-profile para manejar el registro y los perfiles. Me gustaría crear un perfil para el usuario en el momento del registro. He creado un formulario de registro personalizado y lo agregué a urls.py utilizando el tutorial en:

http://dewful.com/?p=70

La idea básica en el tutorial es anular el formulario de registro predeterminado para crear el perfil al mismo tiempo.

forms.py – En mi aplicación de perfiles

from django import forms from registration.forms import RegistrationForm from django.utils.translation import ugettext_lazy as _ from profiles.models import UserProfile from registration.models import RegistrationProfile attrs_dict = { 'class': 'required' } class UserRegistrationForm(RegistrationForm): city = forms.CharField(widget=forms.TextInput(attrs=attrs_dict)) def save(self, profile_callback=None): new_user = RegistrationProfile.objects.create_inactive_user(username=self.cleaned_data['username'], password=self.cleaned_data['password1'], email=self.cleaned_data['email']) new_profile = UserProfile(user=new_user, city=self.cleaned_data['city']) new_profile.save() return new_user 

En urls.py

 from profiles.forms import UserRegistrationForm 

y

 url(r'^register/$', register, {'backend': 'registration.backends.default.DefaultBackend', 'form_class' : UserRegistrationForm}, name='registration_register'), 

Se muestra el formulario y puedo ingresar en Ciudad, pero no guarda ni crea la entrada en la base de datos.

Está a mitad de camino: ha creado con éxito un formulario personalizado que reemplaza al formulario predeterminado. Pero está intentando realizar su procesamiento personalizado con un método save () en su formulario modelo. Eso fue posible en versiones anteriores de django-registration, pero puedo ver por el hecho de que usted especificó un backend en su URL conf de que está usando v0.8.

La guía de actualización dice:

Anteriormente, se esperaba que el formulario utilizado para recostackr datos durante el registro implementara un método save () que crearía la nueva cuenta de usuario. Este ya no es el caso; el backend se encarga de crear la cuenta, por lo que cualquier lógica personalizada debe moverse a un backend personalizado, o conectando a los oyentes con las señales enviadas durante el proceso de registro.

En otras palabras, el método save () en el formulario se ignora ahora que está en la versión 0.8. Debe realizar su procesamiento personalizado con un backend personalizado o con una señal. Elegí crear un back-end personalizado (si alguien ha conseguido que esto funcione con señales, por favor, escriba el código, no pude hacerlo funcionar de esa manera). Debería poder modificar esto para guardarlo en su perfil personalizado.

  1. Crea un regbackend.py en tu aplicación.
  2. Copie el método register () de DefaultBackend en él.
  3. Al final del método, realice una consulta para obtener la instancia de usuario correspondiente.
  4. Guarde los campos de formulario adicionales en esa instancia.
  5. Modifique la URL conf para que apunte a AMBOS el formulario personalizado Y al back-end personalizado

Así que la URL conf es:

 url(r'^accounts/register/$', register, {'backend': 'accounts.regbackend.RegBackend','form_class':MM_RegistrationForm}, name='registration_register' ), 

regbackend.py tiene las importaciones necesarias y es básicamente una copia de DefaultBackend con solo el método register () y la adición de:

  u = User.objects.get(username=new_user.username) u.first_name = kwargs['first_name'] u.last_name = kwargs['last_name'] u.save() 

Como se describe en mi comentario sobre el boleto de Django Trac , hice una metaclase y una mezcla para permitir la herencia múltiple de los ModelForm de ModelForm Django. Con esto, simplemente puede hacer un formulario que permita el registro con campos de usuarios y modelos de perfil al mismo tiempo sin campos de encoding o repetición. Usando mi metaclase y mi mezcla (y también mi combinación de fieldset) puedes hacer:

 class UserRegistrationForm(metaforms.FieldsetFormMixin, metaforms.ParentsIncludedModelFormMixin, UserCreationForm, UserProfileChangeForm): error_css_class = 'error' required_css_class = 'required' fieldset = UserCreationForm.fieldset + [( utils_text.capfirst(UserProfileChangeForm.Meta.model._meta.verbose_name), { 'fields': UserProfileChangeForm.base_fields.keys(), })] def save(self, commit=True): # We disable save method as registration backend module should take care of user and user # profile objects creation and we do not use this form for changing data assert False return None __metaclass__ = metaforms.ParentsIncludedModelFormMetaclass 

Donde UserCreationForm puede ser, por ejemplo, django.contrib.auth.forms.UserCreationForm y UserProfileChangeForm un ModelForm simple para su modelo de perfil. (No olvide establecer editable en False en su clave externa para el modelo de User ).

Con el backend de django-registration que tiene dicho método de registro:

 def register(self, request, **kwargs): user = super(ProfileBackend, self).register(request, **kwargs) profile, created = utils.get_profile_model().objects.get_or_create(user=user) # lambda-object to the rescue form = lambda: None form.cleaned_data = kwargs # First name, last name and e-mail address are stored in user object forms_models.construct_instance(form, user) user.save() # Other fields are stored in user profile object forms_models.construct_instance(form, profile) profile.save() return user 

Tenga cuidado de que la señal de registro se envíe al principio de este método (en método en superclase) y no al final.

De la misma manera, puede hacer un formulario de cambio para la información del usuario y del perfil. Ejemplo de esto puede encontrarlo en mi comentario sobre el boleto de Django Trac mencionado anteriormente.

Con registro 0.8 y posteriores:

Cree una subclase de registration.backends.default.views.RegistrationView en su views.py o equivalente:

 from registration.backends.default.views import RegistrationView class MyRegistrationView(RegistrationView): form_class= MyCustomRegistrationForm def register(self, request, **cleaned_data): new_user= super(MyRegistrationView, self).register(request, **cleaned_data) # here create your new UserProfile object return new_user