Allauth Override SignupForm& UserProfile保存

时间:2016-04-05 16:42:44

标签: django django-forms django-allauth

我一直在尝试为Allauth构建自己的SignupForm并继续遇到问题。

当我尝试使用这样的forms.py时:

class SocialSignupForm(forms.ModelForm):
    class Meta:
        model = Profile
        exclude = ('user',)

def __init__(self, *args, **kwargs):
    self.sociallogin = kwargs.pop('sociallogin')
    user = self.sociallogin.user

username = forms.CharField(max_length=25, label="Username", help_text='', required=True)

视觉上,表单完全没有任何问题。但是,当我尝试提交表单时,我会得到USER_ID为空错误。据推测,save方法试图在创建用户之前保存配置文件。不知道如何更改它的顺序,并且只需要在初始保存后重新运行signup()方法。

我已经尝试过其他一些方法(覆盖form.Form和AllAuth的SocialSignUpForm),没有更好的运气(虽然有一组不同的错误)。

这里的任何输入/指导都会令人惊讶,这让我疯狂。

2 个答案:

答案 0 :(得分:1)

据我了解,SocialSignupForm旨在为您自定义User模型的表单,因此除非Profile是您的用户模型(即它来自AbstractBaseUser),你不能在这里使用它。

如果要自定义表单以添加配置文件信息,则应以相反的方向执行此操作。在表单上定义要用于配置文件的其他字段,但仍保留

class Meta:
    model = User   # or whatever your User model is

事实上,你甚至不应该定义一个Meta类,而是从SignupForm派生出来:

from allauth.account.forms import SignupForm
class MySignupForm(SignupForm):
    ...

然后,您可以覆盖custom_signupsave功能,尝试根据用户模型创建配置文件模型

或者考虑使用信号进行此操作。

答案 1 :(得分:0)

对于覆盖 allauth SignupForm,您应该按照以下步骤操作:

  1. 在您的主目录(src 目录)中创建模板目录,并使用以下格式将此目录名称添加到 TEMPLATES 中的 settings.py

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates'), os.path.join(BASE_DIR, 'templates', 'account')],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]
  1. 之后,你应该从这个路径复制并过去 acount 目录(包含其中的所有文件)( .../your_project_path/your_virtualenv_path/lib/python3.8/site-packages/allauth/templates/account) 到名称为 templates 的新目录。 我的 templates 目录格式 image
  2. 请务必这样做:‍
ACCOUNTS_FORMS = {
    .
    .
    .
    'signup': 'registerations.form.AllauthSignUpForm', # Notic: You must call your own AllauthSignUpForm
    .
    .
    . 
}
ACCOUNT_EMAIL_VERIFICATION = 'none'

‍‍‍‍‍ 4. 现在您已准备好自定义登录、注册和其他 allauth 模板。所以你需要在你的应用程序中创建 forms.py 文件并覆盖 allauth SignupForm:

from allauth.account.forms import SignupForm

class AllauthSignUpForm(SignupForm):
    def __init__(self, *args, **kwargs):
        super(AllauthSignUpForm, self).__init__(*args, **kwargs)
        self.fields['username'] = forms.CharField(
            label='',
            widget=forms.TextInput(
                attrs={
                    'class': 'signup_name_inp text-right mb-4 border-top-0 border-right-0 border-left-0 rounded',
                    'placeholder': 'Username',
                    'dir': 'ltr',
                    'autocomplete': 'off'
                }
            ),
        )
        self.fields['email'] = forms.EmailField(
            label='',
            widget=forms.EmailInput(
                attrs={
                    'class': 'signup_mail_inp text-right mb-4 border-top-0 border-right-0 border-left-0 rounded',
                    'placeholder': 'email',
                    'dir': 'ltr',
                    'autocomplete':'off',
                    'required': 'True'
                },  
            )
        )
        self.fields['password1'] = forms.CharField(
            label='',
            widget=forms.PasswordInput(
                attrs={
                    'class': 'signup_pass_inp1 text-right mb-4 border-top-0 border-right-0 border-left-0 rounded',
                    'placeholder': 'password',
                    'dir': 'rtl',
                    'autocomplete': 'off',
                }
            )
        )
        self.fields['password2'] = forms.CharField(
            label='',
            widget=forms.PasswordInput(
                attrs={
                    'class': 'signup_pass_inp2 text-right mb-4 border-top-0 border-right-0 border-left-0 rounded',
                    'placeholder': 'Repeat password',
                    'dir': 'rtl',
                    'autocomplete': 'off',
                }
            )
        )


    def save(self, request=None):
        # Ensure you call the parent class's save.
        # .save() returns a User object.
        user = super(AllauthSignUpForm, self).save(request)
        # Add your own processing here.
        print(user.username)
        # You must return the original result.
        return user
  1. 最后你应该实现你的视图逻辑。例如:
from .form import AllauthSignUpForm
from allauth.account.views import SignupView

class AllauthSignUpView(SignupView):
    template_name = 'account/signup.html'
    form_class = AllauthSignUpForm
    success_url = reverse_lazy('core:home')

    def get_context_data(self, **kwargs):
        context = super(AllauthSignUpView, self).get_context_data(**kwargs)
        signUpForm = AllauthSignUpForm(self.request.POST or None)
        context['form'] = signUpForm
        return context