本文介绍了Django:仅更新 UpdateView 中已更改的字段的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
我正在使用 UpdateView 来更新一系列字段.但是,我只希望将已修改的字段保存到数据库中.如果在更新过程中未为字段提供值,我希望使用先前的值作为默认值.如果为字段提供了新值,则只应更新该字段.我该如何完成这项工作?
#views.py类帐户更新(更新视图):"""更新帐户;未更改的字段将不会更新."""context_object_name = '帐户'form_class = UpdateForm模板名称 = '账户/update_account.html'success_url = '/accounts/home'def get_object(self, queryset=None):返回 self.request.userdef form_valid(self, form):清洁 = form.cleaned_data#encrypt 普通密码form.instance.password = hash_password(clean['password'])上下文 = {}self.object = context.update(clean, force_update=False)return super(AccountUpdate, self).form_valid(form)#模板{% 扩展 'base.html' %}<title>{% 区块标题 %}更新账户{% endblock %}{% 块内容 %}{{ 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 %}
<form action="" name="edit" method="post">{% csrf_token %}<ul><li>全名</li><li>{{ form.first_name }}{{ form.last_name }}<li>电子邮件</li>
{{ form.email }}<li>密码</li><li>{{ form.password }}</li><li>用户名</li><li>{{ form.username }}</li><ul><li><input type="submit" value="update account"></li></表单><ul><li class="nav"><a href="/accounts/">取消更改</a></li>{% 结束块 %}
所有字段也在models.py
中声明为必需.目前,表单仅在我为每个字段提供值时才有效.
解决方案
我会通过不在表单中包含 password
本身来处理这个问题.相反,我会添加一个新字段(类似于 new_password
)以允许输入新密码.然后,在您的 is_valid
方法中,将密码设置为该字段的散列值(如果有内容).
您还应该使用敏感值过滤工具防止用户密码出现在电子邮件错误报告中.
class UpdateForm(forms.ModelForm):元类:模型 = 用户字段 = ('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):清洁 = form.cleaned_datanew_password = clean.get('new_password')如果新密码:#encrypt 普通密码form.instance.password = hash_password(new_password)return super(AccountUpdate, self).form_valid(form)
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 %}
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 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)
And then in your view:
@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 中已更改的字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!