图像字段未更新的 Django 内联表单集
Django inline-formset with an image field not updating
我有一个列表模型和一个照片模型:
class Listing(models.Model):
title = models.CharField(max_length=255)
<more fields>...
class Photo(models.Model):
image = models.ImageField(upload_to=create_file_path)
listing = models.ForeignKey(Listing, related_name='photos')
我正在使用 CBV UpdateView 来编辑列表。我正在使用这种形式:
class ListingDetailForm(forms.ModelForm):
class Meta:
model = Listing
exclude = []
和 forms.py 中的内联表单集使 deleting/changing 图像成为可能:
PhotoFormset = inlineformset_factory(Listing, Photo, fields='__all__', extra=1)
这是我的观点:
class ListingDetailView(UpdateView):
model = Listing
template_name = 'listing/listing_detail.html'
form_class = ListingDetailForm
success_url = '/store/'
def get_context_data(self, **kwargs):
self.object = self.get_object()
context = super(ListingDetailView, self).get_context_data(**kwargs)
if self.request.POST:
context['form'] = ListingDetailForm(self.request.POST, instance=self.object)
context['photo_form'] = PhotoFormset(self.request.POST, self.request.FILES, instance=self.object)
else:
context['form'] = ListingDetailForm(instance=self.object)
context['photo_form'] = PhotoFormset(instance=self.object)
return context
def post(self, request, *args, **kwargs):
self.object = self.get_object()
form_class = self.get_form_class()
form = self.get_form(form_class)
photo_form = PhotoFormset(self.request.POST)
print photo_form.is_valid()
if form.is_valid() and photo_form.is_valid():
return self.form_valid(form)
else:
return self.form_invalid(form)
def form_valid(self, form):
print 'in form valid for update'
context = self.get_context_data()
base_form = context['form']
photo_form = context['photo_form']
# print base_form
# print photo_form
if base_form.is_valid() and photo_form.is_valid():
print 'forms are valid for update'
base_form.save()
photo_form.save()
return super(ListingDetailView, self).form_valid(form)
else:
return self.render_to_response(self)
和相关模板部分:
{% block body %}
<form action="" method="post">
{% csrf_token %}
{% for field in form %}
{{ field.errors }}
{{ field.label_tag }} {{ field }}<br><br>
{% endfor %}
{% for field in photo_form %}
{{ field.errors }}
{{ field.label_tag }} {{ field }}<br><br>
{% endfor %}
{{ photo_form.management_form }}
<input type="submit" value="Update" />
</form>
{% endblock %}
我遇到的问题是:
1) 如果房源附有照片,通过管理员,如果我不对照片表格进行任何操作,照片表格将无法通过验证,例如仅更改列表模型中的字段。照片表格无效后重新加载页面不显示错误。
2) 选择新照片不会改变当前照片,照片表单不会验证并且显示没有错误。
3) 如果当前没有与列表相关的照片尝试添加一张通过表单验证但实际上并未保存与该列表相关的照片。
删除一张图片(如果列表中附加了一张图片)效果很好。删除图像并更新列表中的其他一些字段有效。如果没有图像更新,则只有列表字段有效。通过表单向列表添加第二张照片不起作用,并且不显示任何表单错误。
我注意到您的表单存在一些问题。
- 您需要在您的表单属性中包含 enctype="multipart/form-data",否则您将无法post 向服务器提交数据
- 如果您绝对需要使用,我会使用 Django 方法呈现表单(form.as_p、form.as_table 或 form.as_ul)手动渲染然后按照官方指南:model formsets
- 在 post 方法中,您的表单集缺少文件和实例
实施这些更改后,您的表单集应该可以正常工作。
我有一个列表模型和一个照片模型:
class Listing(models.Model):
title = models.CharField(max_length=255)
<more fields>...
class Photo(models.Model):
image = models.ImageField(upload_to=create_file_path)
listing = models.ForeignKey(Listing, related_name='photos')
我正在使用 CBV UpdateView 来编辑列表。我正在使用这种形式:
class ListingDetailForm(forms.ModelForm):
class Meta:
model = Listing
exclude = []
和 forms.py 中的内联表单集使 deleting/changing 图像成为可能:
PhotoFormset = inlineformset_factory(Listing, Photo, fields='__all__', extra=1)
这是我的观点:
class ListingDetailView(UpdateView):
model = Listing
template_name = 'listing/listing_detail.html'
form_class = ListingDetailForm
success_url = '/store/'
def get_context_data(self, **kwargs):
self.object = self.get_object()
context = super(ListingDetailView, self).get_context_data(**kwargs)
if self.request.POST:
context['form'] = ListingDetailForm(self.request.POST, instance=self.object)
context['photo_form'] = PhotoFormset(self.request.POST, self.request.FILES, instance=self.object)
else:
context['form'] = ListingDetailForm(instance=self.object)
context['photo_form'] = PhotoFormset(instance=self.object)
return context
def post(self, request, *args, **kwargs):
self.object = self.get_object()
form_class = self.get_form_class()
form = self.get_form(form_class)
photo_form = PhotoFormset(self.request.POST)
print photo_form.is_valid()
if form.is_valid() and photo_form.is_valid():
return self.form_valid(form)
else:
return self.form_invalid(form)
def form_valid(self, form):
print 'in form valid for update'
context = self.get_context_data()
base_form = context['form']
photo_form = context['photo_form']
# print base_form
# print photo_form
if base_form.is_valid() and photo_form.is_valid():
print 'forms are valid for update'
base_form.save()
photo_form.save()
return super(ListingDetailView, self).form_valid(form)
else:
return self.render_to_response(self)
和相关模板部分:
{% block body %}
<form action="" method="post">
{% csrf_token %}
{% for field in form %}
{{ field.errors }}
{{ field.label_tag }} {{ field }}<br><br>
{% endfor %}
{% for field in photo_form %}
{{ field.errors }}
{{ field.label_tag }} {{ field }}<br><br>
{% endfor %}
{{ photo_form.management_form }}
<input type="submit" value="Update" />
</form>
{% endblock %}
我遇到的问题是:
1) 如果房源附有照片,通过管理员,如果我不对照片表格进行任何操作,照片表格将无法通过验证,例如仅更改列表模型中的字段。照片表格无效后重新加载页面不显示错误。
2) 选择新照片不会改变当前照片,照片表单不会验证并且显示没有错误。
3) 如果当前没有与列表相关的照片尝试添加一张通过表单验证但实际上并未保存与该列表相关的照片。
删除一张图片(如果列表中附加了一张图片)效果很好。删除图像并更新列表中的其他一些字段有效。如果没有图像更新,则只有列表字段有效。通过表单向列表添加第二张照片不起作用,并且不显示任何表单错误。
我注意到您的表单存在一些问题。
- 您需要在您的表单属性中包含 enctype="multipart/form-data",否则您将无法post 向服务器提交数据
- 如果您绝对需要使用,我会使用 Django 方法呈现表单(form.as_p、form.as_table 或 form.as_ul)手动渲染然后按照官方指南:model formsets
- 在 post 方法中,您的表单集缺少文件和实例
实施这些更改后,您的表单集应该可以正常工作。