Django-Inscription & Django-Profile, à l'aide de votre propre formulaire personnalisé
j'utilise django-registration et django-profile pour gérer l'enregistrement et les profils. Je voudrais créer un profil pour l'utilisateur au moment de l'inscription. J'ai créé un formulaire d'inscription personnalisé, et ajouté que urls.py utiliser le tutoriel sur:
L'idée de base dans le tutoriel est de remplacer la valeur par défaut formulaire d'inscription pour créer le profil en même temps.
forms.py - Dans mon des profils d'application
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
<!--3 - 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 en ville, cependant il ne sauve pas ou ne crée pas l'entrée dans le DB.
4 réponses
Vous êtes à mi-chemin - vous avez créé 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. C'était possible dans les versions plus anciennes de django-registration, mais je peux voir du fait que vous avez spécifié un backend dans votre conf URL que vous utilisez v0.8.
Auparavant, le formulaire utilisé pour recueillir des données au cours de l'inscription était attendue pour implémenter une méthode save () qui créerait le nouveau compte d'utilisateur. Ce n'est plus le cas; la création de le compte est géré par le backend, et donc, une logique personnalisée devrait être transféré dans un backend personnalisé, ou par connexion auditeurs les signaux envoyé lors de l'inscription.
En d'autres termes, la méthode save() sur le formulaire est ignoré maintenant que vous êtes sur la version 0.8. Vous devez faire votre traitement personnalisé soit avec un backend, ou avec un signal. J'ai choisi de créer un back-end personnalisé (si quelqu'un a obtenu ce travail avec des signaux, s'il vous plaît post code - je n'ai pas été en mesure de le faire fonctionner de cette façon). Vous devriez être capable de le modifier pour enregistrer votre profil personnalisé.
- Créer un regbackend.py dans votre application.
- Copier la méthode register() de DefaultBackend.
- À la fin de la méthode, de faire une requête pour obtenir l'Utilisateur correspondant instance.
- Sauvegardez les champs additionnels du formulaire dans cette instance.
- modifiez le conf URL pour qu'il pointe à la fois vers la forme personnalisée et vers la fin
donc le conf URL 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 essentiellement 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 Trac billet j'ai fait une métaclasse et mixin pour permettre l'héritage multiple pour ModelForm
formulaires Django. Avec cela, vous pouvez simplement faire un formulaire qui permet l'enregistrement avec des champs de l'utilisateur et des modèles de profil en même temps sans champs de codage dur ou se répéter. En utilisant mon métaclasse et mixin (et aussi fieldset mixin) 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,django.contrib.auth.forms.UserCreationForm
formulaire UserProfileChangeForm
un simple ModelForm
pour votre modèle de profil. (Ne pas oublier de mettre editable
False
dans votre clé étrangère User
modèle.)
Avec django-enregistrement backend avoir 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
attention 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 faire un formulaire de modification pour les informations utilisateur et profil. Exemple pour ceci vous pouvez trouver dans mon commentaire sur Django Trac ticket mentionné ci-dessus.
la Solution avec des signaux - ici j'ai écrit comment utiliser des signaux pour sauver des données supplémentaires
Avec l'enregistrement de 0,8 et plus tard:
créer une sous-classe d'enregistrement.backends.défaut.vue.RegistrationView dans votre views.py ou l'é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