2010-04-08 10 views
30

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 personalizada, y ha añadido que a la urls.py usando el tutorial en:Django-Registration & Django-Profile, usando su propio formulario personalizado

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

La idea básica en el tutorial es para anular el formulario de registro por defecto para crear el perfil al mismo hora.

forms.py - En mi perfiles de aplicación se visualiza

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'), 

La forma, y ​​puedo entrar en la ciudad, sin embargo, no guarda ni crea la entrada en el DB.

Respuesta

28

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

El upgrade guide dice:

Anteriormente, el formulario de recogida de datos durante el registro se esperaba para implementar un método save() que sería crear la nueva cuenta de usuario. Esto ya no es el caso; creando la cuenta es manejada por el backend, y por lo tanto cualquier lógica personalizada debe ser movida a un backend personalizado, o por conectando escuchas a 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 hacer su procesamiento personalizado con un back-end personalizado o con una señal. Elegí crear un back-end personalizado (si alguien ha conseguido que esto funcione con las señales, por favor, publique el código; no pude hacerlo funcionar de esa manera). Debería poder modificar esto para guardar en su perfil personalizado.

  1. Crear una regbackend.py en su 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. Modificar la conf URL para que apunte tanto a la forma de encargo y el back-end personalizada

Así que la conf URL 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 sólo el método de registro(), 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() 
+1

gracias por el comentario. Decidió hacer una redirección para crear un perfil en el momento del registro, de esa manera no tiene un perfil para un usuario no activado. Sin embargo, marcará esta pregunta como respondida. – ismail

+0

Tengo el mismo problema con la nueva versión del registro de djando. Shacker, pero dónde exactamente está: "Copie el método register() de DefaultBackend en él." DefaultBackend ??, ¿dónde está? Gracias – Asinox

+2

Asinox - Debe obtenerlo del código fuente de django-registration. Mire en registro/backends/default/__ init__.py – shacker

8

Solution with signals - aquí me escribieron cómo utilizar las señales para salvar adi Datos regionales

+0

¡Una manera excelente y más fácil de hacer eso! –

+0

Me gusta esto, pero se puede simplificar aún más, ya que no es necesario colocar la función "llenar el perfil" y la llamada 'connect()' en un archivo separado (el nombre 'regbackend.py' también podría sea ​​un poco engañoso ya que no está creando un backend) – Agos

+0

¡adivinémoslo así, gracias por la respuesta! – dmitko

10

Como se describe en my comment on Django Trac ticket Hice una metaclase y mixin para permitir herencia múltiple para ModelForm formularios Django. Con esto, puede simplemente hacer un formulario que permita el registro con campos de usuarios y modelos de perfil al mismo tiempo sin campos de codificación rígida o repitiéndose usted mismo. Mediante el uso de mi metaclase y mixin (y también de campos mixin) que 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 

Dónde UserCreationForm puede ser por ejemplo la forma y django.contrib.auth.forms.UserCreationFormUserProfileChangeForm un simple ModelForm para su modelo de perfil. (No se olvide de establecer editable a False en su clave externa a User modelo.)

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

De la misma manera puede hacer un formulario de cambio para el usuario y la información de perfil. Ejemplo de esto lo puedes encontrar en mi comentario sobre el ticket de Django Trac mencionado anteriormente.

+1

Recientemente implementé lo mismo con señales, ¡pero esto es simplemente increíble! Definitivamente necesito aprender a usar las técnicas de metaclass y mixin. –

+1

Me alegro de que te guste. ;-) – Mitar

+0

¿Qué importaciones necesito para que esto funcione? – stanwise

1

Con el registro 0.8 y posterior:

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 
Cuestiones relacionadas