问题
I'm trying to modify the signup form which the user is shown when logging in from a socialaccount provider.
Here's me custom signup form code:
from allauth.socialaccount.forms import SignupForm
from allauth.account.forms import SetPasswordField, PasswordField
class SocialPasswordedSignupForm(SignupForm):
password1 = SetPasswordField(label=_("Password"))
password2 = PasswordField(label=_("Password (again)"))
def confirm_password(self):
print('entered confirm_password')
if ("password1" in self.cleaned_data
and "password2" in self.cleaned_data):
print('password fields found')
if self.cleaned_data['password1'] != self.cleaned_data['password2']:
print('passwords not equal')
raise forms.ValidationError(_("You must type the same password"
" each time."))
print('passwords equal')
return self.cleaned_data["password1"]
else:
print('passwords not found in form')
raise forms.ValidationError(_("Password not found in form"))
def signup(self, request, user):
print('signup in SocialPasswordedSignupForm')
password = self.confirm_password()
user.set_password(password)
user.save()
settings.py:
SOCIALACCOUNT_FORMS = {
'signup': 'users.forms.SocialPasswordedSignupForm'
}
But the problem is, that my signup method never gets called, and so, the confirm_password
method isn't called either, and there's no validation on password being done. That is, if I enter two different passwords, the first password is saved.
What could be wrong?
回答1:
Are you setting this value SOCIALACCOUNT_AUTO_SIGNUP = False ? This is to make sure that upon successful authentication the user is redirected to your signup form.
I came to your link because I had to implement exact same feature. So this is how I have done it on my end.
forms.py
class SocialPasswordedSignupForm(SignupForm):
password1 = SetPasswordField(max_length=6,label=("Password"))
password2 = PasswordField(max_length=6, label=("Password (again)"))
#taken from https://github.com/pennersr/django-allauth/blob/master/allauth/account/forms.py
def clean_password2(self):
if ("password1" in self.cleaned_data and "password2" in self.cleaned_data):
if (self.cleaned_data["password1"] != self.cleaned_data["password2"]):
raise forms.ValidationError(("You must type the same password each time."))
return self.cleaned_data["password2"]
def signup(self, request, user):
user.set_password(self.user, self.cleaned_data["password1"])
user.save()
I got the idea to explore the original code in https://github.com/pennersr/django-allauth/blob/master/allauth/account/forms.py and found out that there is no such function like clean_password1() but there is clean_password2() which is doing the intended work. So just copied it as it is and everything worked :)
If it works for you then don't forget to accept it as answer.
回答2:
I basically created my version of the SignupForm class:
from allauth.account.forms import SetPasswordField, PasswordField
from allauth.account import app_settings
from allauth.account.utils import user_field, user_email, user_username
from django.utils.translation import ugettext_lazy as _
class SocialPasswordedSignupForm(BaseSignupForm):
password1 = SetPasswordField(label=_("Password"))
password2 = SetPasswordField(label=_("Confirm Password"))
def __init__(self, *args, **kwargs):
self.sociallogin = kwargs.pop('sociallogin')
user = self.sociallogin.user
# TODO: Should become more generic, not listing
# a few fixed properties.
initial = {'email': user_email(user) or '',
'username': user_username(user) or '',
'first_name': user_field(user, 'first_name') or '',
'last_name': user_field(user, 'last_name') or ''}
kwargs.update({
'initial': initial,
'email_required': kwargs.get('email_required',
app_settings.EMAIL_REQUIRED)})
super(SocialPasswordedSignupForm, self).__init__(*args, **kwargs)
def save(self, request):
adapter = get_adapter()
user = adapter.save_user(request, self.sociallogin, form=self)
self.custom_signup(request, user)
return user
def clean(self):
super(SocialPasswordedSignupForm, self).clean()
if "password1" in self.cleaned_data \
and "password2" in self.cleaned_data:
if self.cleaned_data["password1"] \
!= self.cleaned_data["password2"]:
raise forms.ValidationError(_("You must type the same password"
" each time."))
def raise_duplicate_email_error(self):
raise forms.ValidationError(
_("An account already exists with this e-mail address."
" Please sign in to that account first, then connect"
" your %s account.")
% self.sociallogin.account.get_provider().name)
def custom_signup(self, request, user):
password = self.cleaned_data['password1']
user.set_password(password)
user.save()
Worked for me, flawlessly. You guys can compare the default SignupForm in socialaccount.forms and my implementation, for the differences.
来源:https://stackoverflow.com/questions/28476106/customizing-django-allauths-socialaccount-signup-form-adding-password-fields