如何自定义用户配置文件时使用 django-allauth

我有个 Django 项目,用的是 Django-Allauth 应用。我需要从注册用户收集额外的数据。我遇到了一个类似的 我有个问题,但不幸的是,没有人回答的配置文件定制部分。

django-allauth提供的文件:

ACCOUNT_SIGNUP_FORM_CLASS(= None)

一个指向自定义表单类(例如 ‘myapp.forms.SignupForm’)的字符串,该类在注册期间用于要求用户输入额外的信息(例如新闻通讯注册、出生日期)。这个类应该实现一个 ‘save’方法,接受新注册的用户作为它的唯一参数。

我是姜戈的新手,正在努力适应。有人能提供这样一个自定义表单类的示例吗?我是否需要添加一个模型类以及到用户对象(如 这个)的链接?

49237 次浏览

创建用户为 OneToOneField 的配置文件模型

class Profile(models.Model):
user = models.OneToOneField(User, verbose_name=_('user'), related_name='profiles')
first_name=models.CharField(_("First Name"), max_length=150)
last_name=models.CharField(_("Last Name"), max_length=150)
mugshot = ImageField(_('mugshot'), upload_to = upload_to, blank=True)
phone= models.CharField(_("Phone Number"), max_length=100)
security_question = models.ForeignKey(SecurityQuestion, related_name='security_question')
answer=models.CharField(_("Answer"), max_length=200)
recovery_number= models.CharField(_("Recovery Mobile Number"), max_length=100)
city=models.ForeignKey(City,related_name='city', blank=True, null=True, help_text=_('Select your City'))
location=models.ForeignKey(Country,related_name='location', blank=True, null=True, help_text=_('Select your Location'))

假设您想在注册期间询问用户的姓/名。您需要将这些字段放在自己的表单中,如下所示:

class SignupForm(forms.Form):
first_name = forms.CharField(max_length=30, label='Voornaam')
last_name = forms.CharField(max_length=30, label='Achternaam')


def signup(self, request, user):
user.first_name = self.cleaned_data['first_name']
user.last_name = self.cleaned_data['last_name']
user.save()

Then, in your settings point to this form:

ACCOUNT_SIGNUP_FORM_CLASS = 'yourproject.yourapp.forms.SignupForm'

请注意,不能在通过 ACCOUNT_FORMSSOCIALACCOUNT_FORMS覆盖表单的同一个文件中定义 SignupForm,因为这将导致循环导入错误。

仅此而已。

使用 pennersr 建议的解决方案,我得到了一个反对警告:

DeprecationWarning: The custom signup form must offer a def signup(self, request, user) method DeprecationWarning)

这是因为 版本0.15的 save 方法已经被弃用,转而使用 def 注册(request,user)方法。

为了解决这个问题,这个例子的代码应该是这样的:

class SignupForm(forms.Form):
first_name = forms.CharField(max_length=30, label='Voornaam')
last_name = forms.CharField(max_length=30, label='Achternaam')


def signup(self, request, user):
user.first_name = self.cleaned_data['first_name']
user.last_name = self.cleaned_data['last_name']
user.save()

在你的 users/forms.py里你写:

from django.contrib.auth import get_user_model
class SignupForm(forms.ModelForm):
class Meta:
model = get_user_model()
fields = ['first_name', 'last_name']
def save(self, user):
user.save()

在设置中. py 你输入:

ACCOUNT_SIGNUP_FORM_CLASS = 'users.forms.SignupForm'

通过这种方式,您不会因为多重用户模型字段定义而破坏 DRY 原则。

Here's what worked for me combining a few of the other answers (none of them are 100% complete and DRY).

yourapp/forms.py:

from django.contrib.auth import get_user_model
from django import forms


class SignupForm(forms.ModelForm):
class Meta:
model = get_user_model()
fields = ['first_name', 'last_name']


def signup(self, request, user):
user.first_name = self.cleaned_data['first_name']
user.last_name = self.cleaned_data['last_name']
user.save()

And in settings.py:

ACCOUNT_SIGNUP_FORM_CLASS = 'yourapp.forms.SignupForm'

This way it uses the model forms so that it's DRY, and uses the new def signup. I tried putting 'myproject.myapp.forms.SignupForm' but that resulted in a error somehow.

@ Shreyas: 下面的解决方案可能不是最干净的,但是很有效。请让我知道,如果你有任何建议,清理它的任何进一步。

要添加不属于默认用户配置文件的信息,首先在 yourapp/model. py 中创建一个模型。阅读一般的 django 文档了解更多,但基本上:

from django.db import models


class UserProfile(models.Model):
user = models.OneToOneField(User, related_name='profile')
organisation = models.CharField(organisation, max_length=100, blank=True)

然后在 yourapp/forms.py 中创建一个表单:

from django import forms


class SignupForm(forms.Form):
first_name = forms.CharField(max_length=30, label='Voornaam')
last_name = forms.CharField(max_length=30, label='Achternaam')
organisation = forms.CharField(max_length=20, label='organisation')


def signup(self, request, user):
user.first_name = self.cleaned_data['first_name']
user.last_name = self.cleaned_data['last_name']
# Replace 'profile' below with the related_name on the OneToOneField linking back to the User model
up = user.profile
up.organisation = self.cleaned_data['organisation']
user.save()
up.save()

我尝试了很多不同的教程,他们都缺少一些东西,重复不必要的代码或做奇怪的事情,以下是我的解决方案,加入所有的选项,我已经找到了工作,我已经把它投入生产,但它仍然没有说服我,因为我希望收到的名字和姓氏的函数,我附加到用户创建的,以避免在表单内创建一个配置文件,但我不能,由于我认为它会帮助你。

Models.py

class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
bio = models.TextField(max_length=500, blank=True)
nationality = models.CharField(max_length=2, choices=COUNTRIES)
gender = models.CharField(max_length=1, choices=GENDERS)


def __str__(self):
return self.user.first_name




@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
if created:
Profile.objects.create(user=instance)


@receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
instance.profile.save()

表格.py

class SignupForm(forms.ModelForm):
first_name = forms.CharField(max_length=100)
last_name = forms.CharField(max_length=100)


class Meta:
model = Profile
fields = ('first_name', 'last_name', 'nationality', 'gender')


def signup(self, request, user):
# Save your user
user.first_name = self.cleaned_data['first_name']
user.last_name = self.cleaned_data['last_name']
user.save()


user.profile.nationality = self.cleaned_data['nationality']
user.profile.gender = self.cleaned_data['gender']
user.profile.save()

设置: py

ACCOUNT_SIGNUP_FORM_CLASS = 'apps.profile.forms.SignupForm'
#models.py


from django.conf import settings


class UserProfile(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
image = models.ImageField(default='users/default.png', upload_to='users')
fields = models.ForeignKey('Field' ,null=True ,on_delete=models.SET_NULL)
category = models.ForeignKey('Category' ,null=True ,on_delete=models.SET_NULL)
description = models.TextField()
interests = models.ManyToManyField('Interests')


...


def save(self, *args, **kwargs):
super().save(*args, **kwargs)


...


def userprofile_receiver(sender, instance, created, *args, **kwargs):
if created:
userprofile = UserProfile.objects.create(user=instance)
else:
instance.userprofile.save()


post_save.connect(userprofile_receiver, sender=settings.AUTH_USER_MODEL)






#forms.py


class SignupForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(SignupForm, self).__init__(*args, **kwargs)
self.fields['first_name'].widget = forms.TextInput(attrs={'placeholder': 'Enter first name'})
self.fields['last_name'].widget = forms.TextInput(attrs={'placeholder': 'Enter last name'})


first_name = forms.CharField(max_length=100)
last_name = forms.CharField(max_length=100)


interests  = forms.ModelMultipleChoiceField(widget=forms.CheckboxSelectMultiple, help_text="Choose your interests", queryset=Interests.objects.all())


image = forms.ImageField(help_text="Upload profile image ")
fields = forms.ChoiceField(help_text="Choose your fields ")
category = forms.ChoiceField(help_text="Choose your category")


class Meta:
model = UserProfile
fields = ('first_name', 'last_name',  'name', 'image', 'fields', 'category', 'description', 'phone', 'facebook', 'twitter', 'skype', 'site', 'address', 'interests' ,'biography')
widgets = {
...
'description': forms.TextInput(attrs={'placeholder': 'Your description'}),
'address': forms.TextInput(attrs={'placeholder': 'Enter address'}),
'biography': forms.TextInput(attrs={'placeholder': 'Enter biography'}),
....
}
def signup(self, request, user):
# Save your user
user.first_name = self.cleaned_data['first_name']
user.last_name = self.cleaned_data['last_name']
user.save()


user.userprofile.image = self.cleaned_data.get('image')
user.userprofile.fields = self.cleaned_data['fields']
user.userprofile.category = self.cleaned_data['category']
user.userprofile.description = self.cleaned_data['description']
interests = self.cleaned_data['interests']
user.userprofile.interests.set(interests)
user.userprofile.save()




# settings.py or base.py


ACCOUNT_SIGNUP_FORM_CLASS = 'nameApp.forms.SignupForm'

就是这样: