Django:阻止某些字段在UpdateView中保存

时间:2013-08-25 19:37:30

标签: python django django-class-based-views

此问题与Django: Only update fields that have been changed in UpdateView

有关

我正在尝试为用户提供更改电子邮件的方式。在我将新电子邮件保存为默认电子邮件之前,我想向新提供的地址发送电子邮件以确保其有效。新提供的电子邮件将保存在数据库的临时表中,但之前(旧)的电子邮件将保持不变,直到验证完毕。

我遇到的问题是,旧电子邮件在验证之前会被新电子邮件覆盖。如何使用UpdateView防止这种情况发生?以下是我的代码:

class AccountUpdate(UpdateView):
    """Updates an account"""

    context_object_name = 'account'
    form_class = UpdateForm
    template_name = 'accounts/update_account.html'
    success_url = '/accounts/home'

    def get_object(self, queryset=None):
        return self.request.user

    @sensitive_variables('new_password')
    @sensitive_post_parameters('new_password')
    def form_valid(self, form):
        account = Account.objects.get(pk=self.request.user.id)
        clean = form.cleaned_data
        new_password = clean.get('new_password')
        old_email = account.email
        new_email = clean.get('email')

        # check for new password and encrypt it before saving
        if new_password:
            #encrypt plain password
            form.instance.password = hash_password(clean['new_password'])

        # check for new email address and save it in temporary field until verified
        # ensure that new email is different and is currently not taken
        if old_email != new_email:
            try:
                # make sure someone else has not used this email as their new email
                temp_taken = Account.objects.get(new_email=new_email)
                if temp_taken:
                    raise ValidationError('An account with this email exist.')

            # save new email and send verification message
            # make sure we set 'DoesNotExist' on the 'Account' object itself
            # it prevents 'str' object has no attribute 'DoesNotExist' error
            except Account.DoesNotExist:
                verifystring = get_random_string()
                self.object.new_email = new_email
                self.object.new_email_verifystring = verifystring
                message = "Hey %s! " \
                      "Please click the link below to verify your new email:" \
                      "<a href='link_here'>Verify Email!</a>" %\
                      (clean['first_name'])
                self.object.email_user(subject='email verification.',
                                   message=message,
                                   from_email='no-reply@localhost')
        else:
            context = {}
            self.object = context.update(first_name=clean.get('first_name'),
                                     last_name=clean.get('last_name'),
                                     username=clean.get('username'),
                                     force_update=False)
        return super(AccountUpdate, self).form_valid(form)

如果其他地方已有答案,请指出。

2 个答案:

答案 0 :(得分:1)

这与基于类的字段没什么关系,但是没有丢失已知有效的地址。

我建议您在Account模型中添加一个字段,名为new_emailunverified_email或其他内容;更改帐户后,实际的email字段不会受到影响,新地址会存储到该新字段中,并会向其发送验证电子邮件。

只有在验证过程完成后,新地址才会存储到电子邮件字段中,从而覆盖旧地址。在更新表格中警告用户他们的旧地址将被使用,直到他们验证新地址为止,这也是谨慎的。

答案 1 :(得分:0)

The problem I'm running into is, the old email gets over-written by the new one before it has been verified.

这不回答如何使用UpdateView防止保存字段的问题,但它解决了上述问题。

# views.py snippet
# because we are using the same 'email' variable to add new email addresses
# 'self.object.email' will be saved with the new provided value
# to prevent this from happening, manually set the 'email' variable to the value
# retrieved from the DB
except Account.DoesNotExist:
            verifystring = get_random_string()
            self.object.email = old_email
            self.object.new_email = new_email