我有一个基本的 User 模型和另外两个候选人和公司
模型User:
email
password
is_company => default=False
表单类:
class CustomUserCreationForm(forms.Form):
email = forms.EmailField(label='Enter email', widget=forms.EmailInput(attrs={'placeholder': 'Email Address', 'spellcheck':'False', 'autofocus':'True'}))
password = forms.CharField(label='Enter password', min_length=8, widget=forms.PasswordInput(attrs={'placeholder': 'Password'}))
def clean_email(self):
email = self.cleaned_data['email'].lower()
r = User.objects.filter(email=email)
if r.count():
raise ValidationError("Email already exists")
return email
def clean_password(self):
password = self.cleaned_data.get('password')
return password
def save(self, commit=True):
user = User.objects.create_user(
self.cleaned_data['email'],
self.cleaned_data['password']
)
return user
我的UserManager:
class UserManager(BaseUserManager):
use_in_migrations = True
def _create_user(self, email, password, **extra_fields):
"""
Creates and saves a User with the given email and password.
"""
try:
validate_email(email)
valid_email = True
except ValidationError:
valid_email = False
if not valid_email:
raise ValueError('Valid Email is required')
email = self.normalize_email(email)
user = self.model(email=email, **extra_fields)
user.set_password(password)
user.save(using=self._db)
subject = 'Activate Your Account'
message = render_to_string('registration/account_activation_email.html', {
'domain': 'example.in',
'user': user,
'uid': urlsafe_base64_encode(force_bytes(user.pk)),
'token': account_activation_token.make_token(user),
})
user.email_user(subject, 'example <admin@example.in>', html_message=message)
return user
def create_user(self, email, password=None, **extra_fields):
extra_fields.setdefault('is_superuser', False)
return self._create_user(email, password, **extra_fields)
def create_superuser(self, email, password, **extra_fields):
extra_fields.setdefault('is_superuser', True)
if extra_fields.get('is_superuser') is not True:
raise ValueError('Superuser must have is_superuser=True.')
return self._create_user(email, password, **extra_fields)
在我的用户创建视图中:
class SignUpView(View):
is_company = False
def get(self, request):
if request.user.is_authenticated():
return redirect(reverse_lazy('dashboard'))
form = CustomUserCreationForm()
return render(request, 'registration/signup.html', {'form': form, 'is_company':self.is_company})
def post(self,request):
form = CustomUserCreationForm(request.POST or None, request.FILES or None)
if form.is_valid():
user = form.save(commit=False)
user.is_active = False
user.is_company = self.is_company
user.save()
return render(request, 'registration/account_activation_sent.html')
return render(request, 'registration/signup.html', {'form': form, 'is_company':self.is_company})
我为上述模型创建了一个post_save信号。
@receiver(post_save, sender=User)
def update_user_profile(sender, instance, created, **kwargs):
if created:
if instance.is_company:
Company.objects.create(user=instance)
instance.company.save()
else:
Candidate.objects.create(user=instance,
first_name=instance.is_company )
instance.candidate.save()
urls.py:
url(r'^accounts/signup/company/',vw.SignUpView.as_view(is_company = True), name='signup_company')
问题是form.save(commit=False)
触发了post_save信号。我最终将instance.is_company
作为False
,从而为公司创建了CandidateProfile。
但是在数据库用户表中,公司的is_company填充为True。
请帮助!
答案 0 :(得分:0)
在处理实例之前,应先尝试断开post_save信号,然后再连接它。
@receiver(post_save, sender=User)
def update_user_profile(sender, instance, created, **kwargs):
# disconnect post_save
post_save.disconnect(update_user_profile, sender=sender)
# do something with your instance
# connect post_save
post_save.connect(update_user_profile, sender=sender)
答案 1 :(得分:0)
在您的表单中,您已覆盖save
,并且始终调用create_user
,该调用将调用user.save(using=self._db)
,即未传递commit
的值
您可以做的是在用户模型中覆盖_create_user
,以将提交值传递给它
class User(AbstractBaseUser):
...
def _create_user(self, username, email, password, commit=True, **extra_fields):
if not username:
raise ValueError('The given username must be set')
email = self.normalize_email(email)
username = self.model.normalize_username(username)
user = self.model(username=username, email=email, **extra_fields)
user.set_password(password)
if commit:
user.save(using=self._db)
return user
然后在您的表单中可以将commit的值传递给它
class CustomUserCreationForm(forms.Form):
def save(self, commit=True):
return User.objects.create_user(
self.cleaned_data['email'],
self.cleaned_data['password'],
commit=False
)
编辑:再次查看此代码,我觉得这很糟糕。 您最好修正表单中的逻辑以进行多次保存
class CustomUserCreationForm(forms.Form):
def save(self, commit=True):
is_create = self.instance.pk is None
user = super().save(commit=commit)
user.set_password(self.cleaned_data['password'])
user.save()
if not is_create:
return user
if user.is_company:
Company.objects.create(user=user)
user.company.save() # not really needed
else:
Candidate.objects.create(user=user, first_name=user.is_company)
user.candidate.save() # not really needed
return user
P.S:我个人不喜欢django信号,因为它们会引起混乱。最好在您的视图或表单保存中执行此操作。您应该只有一种创建新用户的方法,所以这不是大问题。
答案 2 :(得分:0)
将您的参数更改为默认False,然后在保存之前检查是否为真...以您的方式进行操作,如果您以commit false或true进行调用,它们将始终保存在数据库中...因此是触发您的post_save
def save(self, commit=False):
if commit:
user = User.objects.create_user(
self.cleaned_data['email'],
self.cleaned_data['password']
)