it-swarm-pt.tech

Django-Registration e Django-Profile, usando seu próprio formulário personalizado

Estou usando o Django-registration e o Django-profile para lidar com o registro e os perfis. Eu gostaria de criar um perfil para o usuário no momento do registro. Criei um formulário de registro personalizado e o adicionei ao urls.py usando o tutorial em:

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

A idéia básica do tutorial é substituir o formulário de registro padrão para criar o perfil ao mesmo tempo.

forms.py - No meu aplicativo de perfis

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

Em urls.py

from profiles.forms import UserRegistrationForm

e

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

O formulário é exibido e eu posso entrar na cidade, no entanto, ele não salva ou cria a entrada no banco de dados.

31
ismail

Você está no meio do caminho - você criou com êxito um formulário personalizado que substitui o formulário padrão. Mas você está tentando fazer seu processamento personalizado com um método save () no formulário do seu modelo. Isso foi possível em versões mais antigas do registro do Django, mas posso ver pelo fato de que você especificou um back-end na sua URL conf que está usando a v0.8.

O guia de atualização diz:

Anteriormente, esperava-se que o formulário usado para coletar dados durante o registro implementasse um método save () que criaria a nova conta de usuário. Este não é mais o caso; a criação da conta é gerenciada pelo back-end e, portanto, qualquer lógica personalizada deve ser movida para um back-end personalizado ou conectando os ouvintes aos sinais enviados durante o processo de registro.

Em outras palavras, o método save () no formulário está sendo ignorado agora que você está na versão 0.8. Você precisa fazer seu processamento personalizado com um back-end personalizado ou com um sinal. Optei por criar um back-end personalizado (se alguém conseguiu isso trabalhando com sinais, por favor, poste o código - não consegui fazê-lo funcionar dessa maneira). Você deve poder modificar isso para salvar em seu perfil personalizado.

  1. Crie um regbackend.py no seu aplicativo.
  2. Copie o método register () do DefaultBackend para ele.
  3. No final do método, faça uma consulta para obter a instância de Usuário correspondente.
  4. Salve os campos adicionais do formulário nessa instância.
  5. Modifique o URL conf para que aponte para o formulário personalizado E o backend personalizado

Portanto, o URL conf é:

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

regbackend.py possui as importações necessárias e é basicamente uma cópia do DefaultBackend apenas com o método register () e a adição de:

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

Como descrito em meu comentário sobre Django ticket do Trac Eu fiz uma metaclasse e mixin para permitir herança múltipla para os formulários ModelForm Django. Com isso, você pode simplesmente criar um formulário que permita o registro com campos de modelos de usuário e perfil ao mesmo tempo, sem codificar os campos ou se repetir. Usando minha metaclasse e mixin (e também fieldset mixin), você pode:

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

Onde UserCreationForm pode ser, por exemplo, Django.contrib.auth.forms.UserCreationForm E UserProfileChangeForm um simples ModelForm para o seu modelo de perfil. (Não se esqueça de definir editable como False na sua chave estrangeira para o modelo User.)

Com o Django-registration backend com esse 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

Cuidado para que o sinal de registro seja enviado no início deste método (no método na superclasse) e não no final.

Da mesma maneira, você pode fazer um formulário de alteração para as informações do usuário e do perfil. Exemplo para isso, você pode encontrar no meu comentário o ticket Trac Django mencionado acima.

11
Mitar

Com o registro 0.8 e posterior:

Crie uma subclasse de registration.backends.default.views.RegistrationView em seu views.py ou 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
1
tzot