web-dev-qa-db-fra.com

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

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

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

L'idée de base du didacticiel 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 est affiché et je peux entrer dans la ville, mais il ne sauvegarde ni ne crée l'entrée dans la BD.

31
ismail

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

Le guide de mise à nivea dit:

Auparavant, le formulaire utilisé pour collecter les données lors de l'inscription devait implémenter une méthode save () qui créerait le nouveau compte utilisateur. Ce n'est plus le cas; la création du compte est gérée par le backend, et donc toute logique personnalisée doit ê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 sur la 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 fait fonctionner cela avec des signaux, veuillez poster du code - je n'ai pas pu le faire fonctionner de cette façon). Vous devriez pouvoir le modifier pour l'enregistrer dans votre profil personnalisé.

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

L'URL conf est donc:

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() 
29
shacker

Comme décrit dans mon commentaire sur Django ticket Trac J'ai fait une métaclasse et un mixage pour autoriser l'héritage multiple pour les formulaires ModelForm Django. Avec cela, vous pouvez simplement créer un formulaire qui permet l'enregistrement des champs à partir des modèles d'utilisateur et de profil en même temps sans codage en dur ni répétition. En utilisant ma métaclasse et mixin (et aussi 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 le formulaire Django.contrib.auth.forms.UserCreationForm Et UserProfileChangeForm un simple ModelForm pour votre modèle de profil. (N'oubliez pas de définir editable sur False dans votre clé étrangère sur le modèle User.)

Avec le backend Django-registration ayant une telle méthode d'enregistrement:

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

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

De la même manière, vous pouvez créer un formulaire de modification pour les informations d'utilisateur et de profil. Exemple pour cela, vous pouvez trouver dans mon commentaire sur Django ticket Trac mentionné ci-dessus.

11
Mitar

Avec inscription 0.8 et ultérieure:

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
1
tzot