Django:只更新UpdateView中已更改的字段 [英] Django: Only update fields that have been changed in UpdateView

查看:2743
本文介绍了Django:只更新UpdateView中已更改的字段的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用UpdateView来更新一系列字段。但是,我只想将已被修改的字段保存到数据库。如果在更新过程中没有为某个字段提供值,我希望将以前的值用作默认值。如果为一个字段提供了一个新值,那么只有该字段应该被更新。如何做到这一点?

I'm using an UpdateView to update a series of fields. However, I only want fields that have been modified to be saved to the database. If a value was not provided for a field during update process, I want the previous value to be used as the default. If a new value was provided for a field then only that field should be updated. How do I go about accomplishing this?

#views.py
class AccountUpdate(UpdateView):
""" Updates an account; unchanged fields will not be updated."""
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

def form_valid(self, form):
    clean = form.cleaned_data
    #encrypt plain password
    form.instance.password = hash_password(clean['password'])
    context = {}
    self.object = context.update(clean, force_update=False)
    return super(AccountUpdate, self).form_valid(form)

#templates
{% extends 'base.html' %}
<title>{% block title %}Update Account{% endblock %}</title>
{% block content %}
{{ account.non_field_errors }}
<div class="errors" style="list-style-type: none;">
    {% if account.first_name.errors %}{{ account.first_name.errors }}{% endif %}
    {% if account.last_name.errors %}{{ account.last_name.errors }}{% endif %}
    {% if account.email.errors %}{{ account.email.errors }}{% endif %}
    {% if account.password.errors %}{{ account.password.errors }}{% endif %}
    {% if account.username.errors %}{{ account.username.errors }}{% endif %}
</div>
<form action="" name="edit" method="post">
    {% csrf_token %}
    <ul>
        <li>Fullname</li>
       <li> {{ form.first_name }}{{ form.last_name }}</li>
        <li>Email</li>
        <li>{{ form.email }}</li>
        <li>Password</li>
        <li>{{ form.password }}</li>
        <li>Username</li>
        <li>{{ form.username }}</li>
    </ul>
    <ul>
        <li><input type="submit" value="update account"></li>
    </ul>
</form>
<ul>
    <li class="nav"><a href="/accounts/">cancel changes</a></li>
</ul>
{% endblock %}

所有字段也在 models.py 。目前,该表单仅适用于我为每个字段提供值。

All the fields are also declared as required in models.py. Currently the form only works if i provide a value for each field.

推荐答案


我正在使用更新过程中的自定义哈希加密密码。当我访问编辑页面并点击更新按钮时,其当前加密形式的旧密码将被重新加密,从而丢失旧密码

i'm using a custom hash during update process to encrypt passwords. When i visit the edit page and hit update button, the old password in its current encrypted form gets re-encrypted hence losing the old password

我将通过在表单中​​不包含密码来处理。相反,我将添加一个新的字段(例如 new_password ),以允许输入新密码。然后,在 is_valid 方法中,如果有内容,请将该密码设置为该字段的哈希值。

I would handle that by not including password itself in the form. Instead, I would add a new field (something like new_password) to allow entering a new password. Then, in your is_valid method, set the password to the hashed value of that field if there's content.

您还应使用敏感值过滤工具来防止用户密码

You should also use the sensitive value filtering tools to prevent user passwords from showing up in emailed error reports.

class UpdateForm(forms.ModelForm):
    class Meta:
        model = user
        fields = ('first_name', 'last_name', 'email', 'username')
    new_password = forms.CharField(required=False, widget=forms.widgets.PasswordInput)

然后在您的视图中:

@sensitive_variables('new_password')
@sensitive_post_parameters('new_password')
def form_valid(self, form):
    clean = form.cleaned_data
    new_password = clean.get('new_password')
    if new_password:
        #encrypt plain password
        form.instance.password = hash_password(new_password)
    return super(AccountUpdate, self).form_valid(form)

这篇关于Django:只更新UpdateView中已更改的字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆