编辑
请不要浪费时间阅读问题...这是错误的方法!
查看我的答案,了解正确解决方案的逐步指南(附有说明)
TL;DR
我如何使用django-allauth为私人用户和公司用户实现注册?
我正在遵循的方法(是否正确?)
我有以下models
:
class PrivateUser(models.Model):
"""Models a private user account"""
user = models.OneToOneField(User, on_delete=models.CASCADE)
class CompanyUser(models.Model):
"""Models the company's contact person user account"""
user = models.OneToOneField(User, on_delete=models.CASCADE)
class Company(models.Model):
"""Models the company attributes"""
contact_person = models.OneToOneField(User, related_name='company')
name = models.CharField(max_length=50, null=False, blank=False)
vat_no = models.CharField(
# some config and validators
)
# ... other non-relevant fields
现在,在使用django-allauth的一个注册表单的情况下,我需要区分两个用户
PrivateUser
和CompanyUser
。如官方django-allauth文档所述:
因此,为了创建一个独特的表单,我创建了一个抽象模型类,其中包含来自ACCOUNT_SIGNUP_FORM_CLASS (=None)
一个字符串,指向自定义表单类(例如
myapp.forms.SignupForm
),该类在注册期间用于要求用户提供额外的输入(例如新闻通讯订阅、出生日期)。这个类应该实现一个def signup(self, request, user)
方法,其中user表示新注册的用户。
PrivateUser
和CompanyUser
的所有字段加上一个(请注意user_type
字段):class AbstractComprehensiveUser(models.Model):
"""
Little hackish model class needed to handle one single sign up
form for multiple users
"""
USER_TYPE_CHOICES = (
('private', 'Private'),
('company', 'Company'),
)
user_type = models.CharField(
max_length=10,
blank=False,
choices=USER_TYPE_CHOICES
)
# Common fields for either private and company users
first_name = models.CharField(max_length=30, blank=False)
last_name = models.CharField(max_length=30, blank=False)
# Company specific fields
company_name = models.CharField(max_length=50, null=True, blank=True)
company_vat_no = models.CharField(
# some config and validators
null=True,
blank = True
)
# other non-relevant fields
class Meta:
abstract = True
注意:这个类中所有非公共字段都有属性 null=True
和 blank=True
。
然后我按照以下方式创建了自定义的 SignupForm
:
class SignupForm(forms.ModelForm):
first_name = forms.CharField(max_length=30)
last_name = forms.CharField(max_length=30)
class Meta:
model = AbstractComprehensiveUser
fields = (
# Field to differentiate from private and company
# user sign up
'user_type',
# Common fields for either private and company users
'first_name', 'last_name',
# Company specifc fields
'company_name', 'company_vat_no', # etc etc
)
现在的想法是使用一个包含两个表单的模板:
- 一个带有隐藏字段
user_type='private'
,只包含first_name
和last_name
字段的表单 - 一个带有隐藏字段
user_type='company'
,包含来自Company
模型的字段的表单
然后,在SignupForm
中,我将接收到user_type
字段,我可以设置适当的表单,例如:
class PrivateUserSignupForm(forms.ModelForm):
first_name = forms.CharField(max_length=30)
last_name = forms.CharField(max_length=30)
class Meta:
model = PrivateUser
fields = ('first_name', 'last_name')
问题在于当我在
SignupForm.signup()
方法中检索数据时,User
模型已经写入数据库。我希望不保存它,而只是:
- 验证它
- 在
signup
方法中接收数据以填充正确的表单(PrivateUserSignupForm
或CompanyUserSignupForm
) - 验证表单
- 如果没有错误,则保存用户和其他模型
- 如果有错误,则不保存任何内容并警告用户有关错误的信息
问题是...
- 这种方法正确吗?有没有其他方法可以在不引起这些麻烦的情况下完成此操作?
- 如果这种方法是正确的,我该如何处理上述工作流程?
company_signup = CompanyUserSignupView.as_view()
而不是company_signup = CompanyUserRegistrationView.as_view()
。 - cristianget_form_class
方法才能使其正常工作,因为SignupView
定义了该方法,以便返回您在ACCOUNT_FORMS
设置中设置的表单类(如果您设置了的话)。 - Samuel Ochoa