29 votos

Django-registro y Django-perfil, utilizando su propio formulario personalizado

Estoy haciendo uso de django-registro y django-perfil para manejar el registro y perfiles. Me gustaría crear un perfil para el usuario en el momento de la inscripción. He creado un formulario de registro personalizado, y añadió que a la urls.py usando el tutorial:

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

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

forms.py - En mis perfiles de la aplicación

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 entrar en la Ciudad, sin embargo no guardar o crear la entrada en la base de datos.

28voto

shacker Puntos 3348

Usted está a mitad de camino - usted ha construido un formulario personalizado que reemplaza al formulario predeterminado. Pero usted está tratando de hacer su procesamiento personalizado con un método save() en su modelo de formulario. Que era posible en versiones anteriores de django-registro, pero puedo ver en el hecho de que usted especifica un backend en su URL conf que está utilizando v0.8.

La actualización de la guía dice:

Anteriormente, el formulario utilizado para recoger datos durante el registro se esperaba para implementar un método save() que iba a crear la nueva cuenta de usuario. Este no es el caso; la creación de la cuenta es manejada por el backend, y así una lógica personalizada debe ser se trasladó en una costumbre backend, o por la conexión de los oyentes a las señales enviado durante el proceso de registro.

En otras palabras, el método save() en el formulario que está siendo ignorada ahora que estás en la versión 0.8. Usted necesita hacer su procesamiento personalizado, ya sea con una costumbre backend o con una señal. Decidí crear un personalizado de back-end (si alguien ha hecho este trabajo con señales, por favor, código postal - yo no era capaz de hacerlo funcionar de esa manera). Usted debe ser capaz de modificar esto para salvar a su perfil personalizado.

  1. Crear un regbackend.py en tu aplicación.
  2. Copia del registro() método de DefaultBackend en ella.
  3. Al final del método, hacer una consulta para obtener la correspondiente instancia de Usuario.
  4. Guarde el formulario adicional de los campos en esa instancia.
  5. Modificar la dirección URL conf para que apunte a AMBOS el formulario personalizado, Y la costumbre de back-end

Así que el URL conf es:

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

regbackend.py tiene la necesaria importación y básicamente es una copia de DefaultBackend sólo con el método de 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() 

9voto

Mitar Puntos 1621

Como se describe en mi comentario sobre Django billete Trac hice un metaclass y mixin para permitir la herencia múltiple para ModelForm Django formas. Con esto puedes hacer un formulario que permite el registro con los campos de usuario y perfil de los modelos, al mismo tiempo, sin codificar campos o repetir lo mismo. Mediante el uso de mi metaclass y mixin (y también fieldset mixin) que usted puede 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 formulario y UserProfileChangeForm simple ModelForm para su modelo de perfil. (No olvides poner editable a False de su clave externa a User modelo).

Con django-registro de backend tener tal 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 el registro de la señal se envía al principio de este método (en el método en la superclase) y no al final.

De la misma manera se puede hacer un formulario de cambio de usuario y la información de perfil. Ejemplo de esto se puede encontrar en mi comentario sobre Django billete Trac se mencionó anteriormente.

8voto

dmitko Puntos 2010

Solución con señales - aquí escribí cómo utilizar señales para guardar datos adicionales

1voto

tzot Puntos 32224

Con registro de 0,8 y más adelante:

Crear 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

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by: