我在我的应用程序中创建了UserProfile
模型:
class UserProfile(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
primary_key=True,
verbose_name=_('user'),
related_name='user_profile')
locality = models.CharField(max_length=85)
voivodship = models.CharField(max_length=20,
choices=Vovoidship.choices,
validators=[Vovoidship.validator])
postcode = models.IntegerField()
street = models.CharField(max_length=75)
building = models.SmallIntegerField()
premises = models.CharField(max_length=80)
phonenumber = PhoneNumberField(blank=True)
@staticmethod
def post_save_create(sender, instance, created, **kwargs):
if created:
profile, created = UserProfile.objects.get_or_create(user=instance)
post_save.connect(UserProfile.post_save_create, sender=User)
现在,我陷入了自己的陷阱。我不想放松约束并在数据库中保留需要填充地址字段的要求。我正在使用django-allauth
。使用设置ACCOUNT_SIGNUP_FORM_CLASS = 'management.forms.SignupForm'
解决了传统注册表单的问题,如果用户首次使用社交帐户登录,则出于明显原因我遇到了约束违规:
IntegrityError at /accounts/google/login/callback/
null value in column "postcode" violates not-null constraint
DETAIL: Failing row contains (4, , , null, , null, , ).
因此,问题是,如何正确实现填写应用程序UserProfile
中字段信息的请求?令我感到惊讶的是django-allauth
没有像ACCOUNT_SIGNUP_FORM_CLASS
一样处理内置处理程序。
当我对Django new 时,请假设我不知道一些事情,而不是显而易见的事情。感谢。
答案 0 :(得分:0)
我认为你需要:
1.-创建自定义注册类,以便您执行其他工作
class SignupForm(forms.Form):
locality = forms.CharField(max_length=85)
voivodship = forms.CharField(max_length=20)
postcode = forms.IntegerField()
etc.
def signup(self, request, user):
# I think the profile will exist at this point based on
# your post_save_create. But if not, just create it here
if user.user_profile:
user.user_profile.locality = self.cleaned_data['locality']
user.user_profile.voivodship = self.cleaned_data['voivodship']
user.user_profile.postcode = self.cleaned_data['postcode']
...
user.user_profile.save()
2.-设置ACCOUNT_SIGNUP_FORM_CLASS = 'yourproject.yourapp.forms.SignupForm'
让allauth使用您的表单
3.-设置SOCIALACCOUNT_AUTO_SIGNUP=False
以确保即使使用社交注册也可以显示表单。
答案 1 :(得分:0)
对davka有一些功劳,我已经设法形成了一个有效的解决方案,需要在UserProfile
类的signup()
方法中创建SignupForm
对象,但由于数据库的原因/ model约束它必须在创建期间填充数据 。结果:
class SignupForm(ModelForm):
first_name = CharField()
last_name = CharField()
class Meta:
model = UserProfile
exclude = ['user', 'phonenumber']
def signup(self, request, user):
user.first_name = self.cleaned_data['first_name']
user.last_name = self.cleaned_data['last_name']
profile, created = UserProfile.objects.get_or_create(
user=user, defaults={
'locality': self.cleaned_data['locality'],
'voivodship': self.cleaned_data['voivodship'],
'postcode': self.cleaned_data['postcode'],
'street': self.cleaned_data['street'],
'building': self.cleaned_data['building'],
'premises': self.cleaned_data['premises'],
})
if created: # This prevents saving if profile already exist
profile.save()
该解决方案并不完全符合DRY原则,但显示了这一想法。更进一步,它可能会迭代匹配模型字段的结果。
需要在settings.py
中正确设置两个元素:
ACCOUNT_SIGNUP_FORM_CLASS = 'yourapp.forms.SignupForm'
在allauth
SOCIALACCOUNT_AUTO_SIGNUP = False
这 - 与直觉相反 - 让allauth
在完成注册之前显示表单如果用户选择社交登录但没有帐户;如果帐户已经存在(用户名和/或电子邮件地址取决于其他设置),它可以安全地工作,因为不允许完成注册(为什么他们称之为注册?)和用户被迫登录并链接社交帐户。