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:
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.
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é.
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()
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
Où 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.
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