[英]Django-allauth - Custom Sign Up with OneToOneField
我使用两个分组的 forms 创建了一个注册表单,它一直运行良好,但我想使用 django-allauth 的功能(仅使用电子邮件登录,发送确认电子邮件......)。 然而,即使阅读一些主题我仍然不能。
forms.py
class ExtendedUserCreationForm(UserCreationForm):
email = forms.EmailField(required=True, label="E-mail")
first_name = forms.CharField(max_length=30, label="Nome")
last_name = forms.CharField(max_length=30, label="Sobrenome")
class Meta:
model = User
fields = ('first_name', 'last_name', 'username', 'email', 'password1', 'password2')
def save(self, commit=True):
user = super().save(commit=False)
user.email = self.cleaned_data['email']
user.first_name = self.cleaned_data['first_name']
user.last_name = self.cleaned_data['last_name']
if commit:
user.save()
return user
class UserProfileForm(forms.ModelForm):
class Meta:
model = UserProfile
fields = ('sexo', 'data_nascimento', 'foto', 'sobre_mim', 'telefone', 'paroquia',
'cidade','estado', 'cep', 'possui_filhos', 'facebook', 'instagram')
CIDADES = []
for i in cidadesReader:
if i[1] not in CIDADES:
CIDADES.append(i[1])
widgets = {
'cidade': floppyforms.widgets.Input(datalist=CIDADES, attrs={'autocomplete': 'off'}),
}
视图.py
def signup(request):
if request.method == 'POST':
form = ExtendedUserCreationForm(request.POST)
profile_form = UserProfileForm(request.POST, request.FILES)
if form.is_valid() and profile_form.is_valid():
user = form.save()
profile = profile_form.save(commit=False)
profile.user = user
profile.save()
username = form.cleaned_data.get('username')
password = form.cleaned_data.get('password1')
user = authenticate(username=username, password=password)
#login(request, user)
return redirect('home')
else:
form = ExtendedUserCreationForm()
profile_form = UserProfileForm()
context = {'form': form, 'profile_form' : profile_form}
return render(request, 'registration/signup.html', context)
注册.html
{% extends '_base.html' %}
{% load crispy_forms_tags %}
{% block title %}Cadastrar{% endblock title %}
{% block content %}
<h2>Criar Perfil</h2>
<form novalidate method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form|crispy }}
{{ profile_form|crispy }}
<button class="btn btn-success" type="submit">Cadastrar</button>
</form>
{% endblock content %}
模型.py
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
SEXOS = (
('M', 'Masculino'),
('F', 'Feminino'),
)
sexo = models.CharField(max_length=1, choices=SEXOS)
data_nascimento = models.DateField(validators=[idade_minima])
...
我试过在settings.py中使用ACCOUNT_SIGNUP_FORM_CLASS和ACCOUNT_FORMS选项,但是没有用。
我尝试进行一些调整,如在这个主题中类似于我的问题: Django allauth save custom user profile fields with signup form
例如,我在models.py中对其进行了更改,并且确实进行了migrate :
user = models.OneToOneField(User, on_delete=models.CASCADE, unique=True, related_name ='profile')
经过多次尝试,最常见的错误是:
RelatedObjectDoesNotExist at /accounts/signup/
User has no profile.
编辑:
我在 UserProfile 中更改了我的 slug,因为它取决于用户(名字)。 错误发生了变化:
IntegrityError at /accounts/signup/
NOT NULL constraint failed: profiles_userprofile.user_id
但是UserProfile 没有用户在决赛中继续。 (在settings.py中使用: ACCOUNT_SIGNUP_FORM_CLASS = 'profiles.forms.UserProfileForm'
。来自追溯的详细信息:
...lib/python3.6/site-packages/allauth/account/views.py in dispatch
215 return super(SignupView, self).dispatch(request, *args, **kwargs)
.../lib/python3.6/site-packages/allauth/account/views.py in post
104 response = self.form_valid(form)
...lib/python3.6/site-packages/allauth/account/views.py in form_valid
231 self.user = form.save(self.request)
...lib/python3.6/site-packages/allauth/account/forms.py in save
405 self.custom_signup(request, user)
...lib/python3.6/site-packages/allauth/account/forms.py in custom_signup
359 custom_form.save(user)
...profiles/models.py in save
super(UserProfile, self).save(*args, **kwargs)
▼ Local vars
Variable Value
__class__
<class 'profiles.models.UserProfile'>
args ()
kwargs {}
self Error in formatting: RelatedObjectDoesNotExist: UserProfile has no user.
slug_name 'nome-sp-260221205510'
信号
使用信号改变了错误。 我在models.py中添加了它:
@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
if created:
UserProfile.objects.create(user=instance)
错误:
ValueError at /accounts/signup/
The 'foto' attribute has no file associated with it.
然后我尝试删除 foto 字段,但另一个错误发生在另一个字段中:
IntegrityError at /accounts/signup/
NOT NULL constraint failed: profiles_userprofile.data_nascimento
提前感谢您的帮助。
在UserProfile.save()
中触发了错误UserProfile has no user
。 您第一次在视图中使用commit=False
调用它,然后才设置用户:
# your code from the question
profile = profile_form.save(commit=False)
profile.user = user
profile.save()
我猜UserProfile.save
会读取user
字段来创建 slug。 如果commit=False
,您可以跳过它,或者如果您像这样更改它,它可能已经工作:
profile_form.instance.user = user
profile.save()
另一个常见的解决方案是,在初始化表单时向用户提供,但是您必须稍微更改当前视图代码退出。
我达到了! 无需使用信号。 以下是更改:
forms.py
我需要使用单个 class:
class SignupForm(forms.ModelForm):
first_name = forms.CharField(max_length=30, label="Nome")
last_name = forms.CharField(max_length=30, label="Sobrenome")
class Meta:
model = UserProfile
fields = ('sexo', 'data_nascimento', 'foto', 'sobre_mim','telefone','paroquia',
'cidade','estado', 'cep', 'possui_filhos', 'facebook', 'instagram')
CIDADES = []
for i in cidadesReader:
if i[1] not in CIDADES:
CIDADES.append(i[1])
widgets = {
'cidade': floppyforms.widgets.Input(datalist=CIDADES, attrs={'autocomplete': 'off'}),
}
field_order = ['first_name', 'last_name', 'email', 'password1', 'password2',
'sexo', 'data_nascimento', 'foto', 'sobre_mim','telefone','paroquia',
'cidade','estado', 'cep', 'possui_filhos', 'facebook', 'instagram']
def signup(self, request, user):
user.first_name = self.cleaned_data['first_name']
user.last_name = self.cleaned_data['last_name']
profile, created = models.UserProfile.objects.get_or_create(user=user)
profile.sexo = self.cleaned_data['sexo']
profile.data_nascimento = self.cleaned_data['data_nascimento']
def compressImage(foto):
...
return foto
profile.foto = compressImage (self.cleaned_data['foto'])
profile.sobre_mim = self.cleaned_data['sobre_mim']
profile.telefone = self.cleaned_data['telefone']
profile.paroquia = self.cleaned_data['paroquia']
profile.cidade = self.cleaned_data['cidade']
profile.estado = self.cleaned_data['estado']
profile.cep = self.cleaned_data['cep']
profile.possui_filhos = self.cleaned_data['possui_filhos']
profile.facebook = self.cleaned_data['facebook']
profile.instagram = self.cleaned_data['instagram']
user.save()
profile.save()
笔记:
我在models.py中使用 function 来压缩图像。 纠正错误
ValueError at /accounts/signup/
The 'foto' attribute has no file associated with it
我不得不把它带到 forms.py
设置.py
ACCOUNT_SIGNUP_FORM_CLASS = 'profiles.forms.SignupForm'
模型.py
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, unique=True, related_name ='profile')
SEXOS = (
('M', 'Masculino'),
('F', 'Feminino'),
)
sexo = models.CharField(max_length=1, choices=SEXOS)
...
笔记:
有必要逐场测试。 有时会出现一些错误,例如NOT NULL constraint failed
ou no such table
。 这些问题的解决方案:
null=True
(临时)makemigrations
和migrate
注册.html
只需要{{ form|crispy }}
(我可以删除{{ profile_form|crispy }}
)
<form novalidate method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form|crispy }}
<button class="btn btn-success" type="submit">Cadastrar</button>
</form>
谢谢你的帮助,@Risadinha。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.