在django中替换文件
我有一个标准表单来编辑一个包含文件字段的对象。当我添加一个新的配置文件时,一切正常,但当我想修改一个字段时,就会出现问题:当我不包括request.FILES时,所有字段都会在表单中检索,并且可以毫无问题地更新,除了化身(filefield),但是当我添加request.FILES时,输入中不再检索字段,而且表格无效。我做错了什么 models.py:在django中替换文件,django,django-forms,Django,Django Forms,我有一个标准表单来编辑一个包含文件字段的对象。当我添加一个新的配置文件时,一切正常,但当我想修改一个字段时,就会出现问题:当我不包括request.FILES时,所有字段都会在表单中检索,并且可以毫无问题地更新,除了化身(filefield),但是当我添加request.FILES时,输入中不再检索字段,而且表格无效。我做错了什么 models.py: from django.db import models class Profile(models.Model): name = mo
from django.db import models
class Profile(models.Model):
name = models.CharField(max_length=45)
email = models.EmailField()
avatar = models.FileField(upload_to="avatars/")
def __str__(self):
return self.name
forms.py:
from django import forms
from .models import Profile
class EditUserForm(forms.ModelForm):
class Meta:
model = Profile
fields = ["name", "email", "avatar"]
profile.html:
<form method="POST">
{% csrf_token %}
<div class="col-md-12">
<div class="row border m-3 p-5">
<div class="col-md-6">Name</div>
<div class="col-md-6">{{ form.name }}</div>
</div>
<div class="row border m-3 p-5">
<div class="col-md-6">Email</div>
<div class="col-md-6">{{ form.email }}</div>
</div>
<div class="row border m-3 p-5">
<div class="col-md-6">Avatar</div>
<div class="col-md-6">
<img src="{{ profile.avatar.url }}" width="100rem" />
{{ form.avatar }}
</div>
</div>
<div class="row">
<button type="submit" class="btn btn-success">Save</button>
</div>
</div>
</form>
尝试如下重构代码:(如果我遗漏了什么,请编辑它。form.is_有效后,应在上下文中发送相同的表单以显示错误
def profile(request, pk):
profile_instance = Profile.objects.get(id=pk)
form = EditUserForm(instance = profile_instance)
if request.method == "POST":
form = EditUserForm(request.POST, request.FILES, instance = profile_instance)
if form.is_valid():
profile = form.save(commit=False)
profile.save()
form = EditUserForm(instance = profile_instance)
context = {
'profile': profile_instance,
'form': form,
}
return render(request, "app/profile.html", context)
特别感谢@bruno desthuilliers和@dirkgroten。 以下是解决这两个问题的答案:
def profile(request, pk):
if request.method == 'POST':
form = EditUserForm(request.POST, request.FILES, instance = Profile.objects.get(id=pk))
if form.is_valid():
profile = form.save(commit=False)
profile.save()
return redirect('profile', pk)
else:
form = EditUserForm(instance = Profile.objects.get(id=pk))
context = {
'profile': Profile.objects.get(id=pk),
'form': form,
}
return render(request, "app/profile.html", context)
首先,您需要将(html)表单的enctype设置为“multipart/form data”(cf),否则
request.FILES
将为空。然后您希望在模板中实际显示表单的验证错误。最后,您应该始终在成功发布后重定向(post redirect get pattern)为了防止重复提交。它现在正在工作,谢谢。不,我的代码中已经有enctype,但问题是返回渲染,我将其更改为重定向,它工作了。但是,前两个字段(名称和电子邮件)未在表单中填充。如果是GET
请求,则不应使用数据实例化表单。这是因为如果传递数据(通过传入request.POST
)并且数据为空,您的表单被绑定,初始值被设置为数据值。请完全按照如下所示操作:实例化EditUserForm(实例=…)
如果是获取
请求。并且仅在有效表单的情况下重定向。包含使正确的基于函数的视图处理表单所需的确切代码。此答案不正确,因为当表单成功提交时,它不会重定向。即使表单位于同一视图,也应始终重定向。
def profile(request, pk):
if request.method == 'POST':
form = EditUserForm(request.POST, request.FILES, instance = Profile.objects.get(id=pk))
if form.is_valid():
profile = form.save(commit=False)
profile.save()
return redirect('profile', pk)
else:
form = EditUserForm(instance = Profile.objects.get(id=pk))
context = {
'profile': Profile.objects.get(id=pk),
'form': form,
}
return render(request, "app/profile.html", context)