31 votes

Django-Registration & Django-Profile, en utilisant votre propre formulaire personnalisé

J'utilise django-registration et django-profile pour gérer les inscriptions et les profils. Je voudrais créer un profil pour l'utilisateur au moment de l'enregistrement. J'ai créé un formulaire d'enregistrement personnalisé, et je l'ai ajouté à urls.py en utilisant le tutoriel sur :

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

L'idée de base du tutoriel est de remplacer le formulaire d'inscription par défaut pour créer le profil en même temps.

forms.py - Dans mon application de profils

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

Dans urls.py

from profiles.forms import UserRegistrationForm

et

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

Le formulaire s'affiche, et je peux saisir la ville, mais il n'enregistre pas ou ne crée pas l'entrée dans la base de données.

29voto

shacker Points 3348

Vous êtes à mi-chemin : vous avez réussi à créer un formulaire personnalisé qui remplace le formulaire par défaut. Mais vous essayez d'effectuer votre traitement personnalisé avec une méthode save() sur votre formulaire modèle. C'était possible dans les anciennes versions de django-registration, mais je peux voir d'après le fait que vous avez spécifié un backend dans votre URL conf que vous utilisez la v0.8.

El guide de mise à niveau dice:

Auparavant, le formulaire utilisé pour recueillir données lors de l'enregistrement devait implémenter une méthode save() qui créerait le nouveau compte utilisateur. Ce n'est plus le cas ; la création du le compte est géré par le backend, et donc toute logique personnalisée doit être être déplacée dans un backend personnalisé, ou en connectant des écouteurs aux signaux envoyés pendant le processus d'enregistrement.

En d'autres termes, la méthode save() du formulaire est ignorée maintenant que vous êtes en version 0.8. Vous devez effectuer votre traitement personnalisé soit avec un backend personnalisé, soit avec un signal. J'ai choisi de créer un back-end personnalisé (si quelqu'un a réussi à le faire fonctionner avec des signaux, merci de poster le code - je n'ai pas réussi à le faire fonctionner de cette façon). Vous devriez être capable de modifier ceci pour enregistrer votre profil personnalisé.

  1. Créez un fichier regbackend.py dans votre application.
  2. Copiez la méthode register() de DefaultBackend dans celui-ci.
  3. À la fin de la méthode, effectuez une requête pour obtenir l'instance d'utilisateur correspondante.
  4. Enregistrez les champs de formulaire supplémentaires dans cette instance.
  5. Modifiez l'URL conf pour qu'elle pointe vers le formulaire personnalisé ET le back-end personnalisé.

Donc l'URL conf est :

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

regbackend.py a les importations nécessaires et est fondamentalement une copie de DefaultBackend avec juste la méthode register(), et l'ajout de :

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

11voto

Mitar Points 1621

Comme décrit dans mon commentaire sur le ticket Trac de Django J'ai créé une métaclasse et un mixin pour permettre l'héritage multiple pour les éléments suivants ModelForm Formulaires Django. Avec cela, vous pouvez simplement faire un formulaire qui permet l'enregistrement avec les champs des modèles d'utilisateur et de profil en même temps sans coder les champs en dur ou vous répéter. En utilisant ma métaclasse et mon mixin (et aussi le mixin fieldset) vous pouvez faire :

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

UserCreationForm peut être par exemple django.contrib.auth.forms.UserCreationForm et UserProfileChangeForm un simple ModelForm pour votre modèle de profil. (N'oubliez pas de définir editable à False dans votre clé étrangère à User modèle.)

Avec le backend django-registration ayant une telle méthode register :

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

Faites attention à ce que le signal d'enregistrement soit envoyé au début de cette méthode (dans la méthode de la superclasse) et non à la fin.

De la même manière, vous pouvez créer un formulaire de modification pour les informations relatives à l'utilisateur et au profil. Vous trouverez un exemple dans mon commentaire sur le ticket Django Trac mentionné ci-dessus.

8voto

dmitko Points 2010

Solution avec signaux - J'ai écrit ici comment utiliser les signaux pour sauvegarder des données supplémentaires.

1voto

tzot Points 32224

Avec l'enregistrement 0.8 et plus :

Créez une sous-classe de registration.backends.default.views.RegistrationView dans votre views.py ou équivalent :

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X