簡體   English   中英

Django post_signal在form.save上觸發(commit = False)

[英]django post_signal triggered on form.save(commit=False)

我有一個基本的用戶模型和另外兩個模型候選人公司

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_companyFalse ,從而為公司創建CandidateProfile。

但是數據庫用戶表使用is_company填充為公司的True。

請幫忙!

在處理實例之前,應先嘗試斷開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)

在您的表單中,您已覆蓋save ,並且始終調用create_user ,后者將調用user.save(using=self._db)即未傳遞commit的值

您可以做的是在用戶模型中覆蓋_create_user ,將commit的值傳遞給它

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

PS:我個人不喜歡django信號,因為它們會引起混亂。 最好在您的視圖或表單保存中執行此操作。 您應該只有一種創建新用戶的方法,所以這不是一個大問題。

將您的參數更改為默認False,然后在保存之前檢查是否為真...如果您用commit false或true進行調用,它們將始終保存在數據庫中...因此,它們會觸發您的操作后保存

def save(self, commit=False):
    if commit:
        user = User.objects.create_user(
            self.cleaned_data['email'],
            self.cleaned_data['password']
        )

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM