我有一个包含ImageField的modelforms的formset。 点击初始表格附近的删除复选框,然后提交按钮 - 我在表格集中有相同数量的表格,并且初始表格的数量相同,但现在已经“删除”的表格没有价值且没有删除复选框(复选框已启用)管理面板,我假设它的小部件呈现)。我做错了什么?
Mixin 结合创建和更新视图:
class HumanAddEditMixin(object):
u"""
"""
form_class = HumanForm
model = Human
template_name = 'human/add_edit.html'
object = None
@method_decorator(login_required)
def dispatch(self, request, *args, **kwargs):
return super(HumanAddEditMixin, self).dispatch(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
if self.object:
form = self.form_class(request.POST, instance=self.object)
sign_formset = SignFormSet(request.POST, request.FILES, instance=self.object)
description_formset = DescriptionFormSet(request.POST, request.FILES, instance=self.object)
doc_formset = DocFormSet(request.POST, instance=self.object)
else:
form = self.form_class(request.POST)
sign_formset = SignFormSet(request.POST, request.FILES)
description_formset = DescriptionFormSet(request.POST, request.FILES)
doc_formset = DocFormSet(request.POST)
if form.is_valid() and sign_formset.is_valid() and description_formset.is_valid() and doc_formset.is_valid():
return self.form_valid(form, sign_formset, description_formset, doc_formset)
else:
return self.form_invalid(form, sign_formset, description_formset, doc_formset)
def form_valid(self, form, sign_formset, description_formset, doc_formset):
if not self.object:
self.object = form.save()
sign_formset.instance = self.object
description_formset.instance = self.object
doc_formset.instance = self.object
sign_formset.save()
description_formset.save()
doc_formset.save()
return HttpResponseRedirect(self.get_success_url())
def form_invalid(self, form, sign_formset, description_formset, doc_formset):
return self.render_to_response(
self.get_context_data(
form=form,
sign_formset=sign_formset,
description_formset=description_formset,
doc_formset=doc_formset
)
)
def get_success_url(self):
return reverse('human:list')
CreateView 看起来效果很好:
class HumanAddView(HumanAddEditMixin, CreateView):
def get_context_data(self, **kwargs):
context = super(HumanAddView, self).get_context_data(**kwargs)
context['sign_formset'] = SignFormSet(instance=self.model())
context['description_formset'] = DescriptionFormSet(instance=self.model())
context['doc_formset'] = DocFormSet(instance=self.model())
return context
的UpdateView:
class HumanUpdateView(HumanAddEditMixin, UpdateView):
pk_url_kwarg = 'human_id'
def dispatch(self, request, *args, **kwargs):
self.object = get_object_or_404(self.model, pk=kwargs[self.pk_url_kwarg])
return super(HumanUpdateView, self).dispatch(request, *args, **kwargs)
def get_context_data(self, **kwargs):
context = super(HumanUpdateView, self).get_context_data(**kwargs)
context['sign_formset'] = SignFormSet(instance=self.object)
context['description_formset'] = DescriptionFormSet(instance=self.object)
context['doc_formset'] = DocFormSet(instance=self.object)
return context
Formsets声明:
SignFormSet = inlineformset_factory(Human, HumanSignImage, form=HumanSignImageForm, extra=1)
DescriptionFormSet = inlineformset_factory(Human, HumanDescriptionImage, form=HumanSignImageForm, extra=1)
DocFormSet = inlineformset_factory(Human, HumanDocImage, form=HumanDocImageForm, extra=1)
其中一个带有图像的模型(在SignFormSet中)和它的模型形式(只有crispy-form帮助器):
class HumanSignImage(models.Model):
human = models.ForeignKey('Human', related_name='sign_images')
image = models.ImageField(upload_to=get_file_path, verbose_name=u'', blank=True, null=True)
def __unicode__(self):
return self.image.name
class HumanSignImageForm(CommonImageModelFormWithHelper):
class Meta:
model = HumanSignImage
答案 0 :(得分:0)
最后我发现我的问题是管理员面板上有两种复选框类型:清除和删除。由于某种原因(使用can_delete = True crispy-forms 不呈现删除复选框here is an answer),我误认为清除是删除强>
或(没有crispy-forms)覆盖ClearableFileInput小部件(没有清除,但删除),类似的东西:
class ImageFileInput(ClearableFileInput):
template_with_initial = '{initial} {input} {delete}'
def delete_checkbox_name(self, name):
"""
Given the name of the file input, return the name of the DELETE checkbox
input.
"""
tmp_list = name.split('-')
del tmp_list[-1]
delete_checkbox_name = '-'.join(tmp_list)
return delete_checkbox_name + '-DELETE'
def delete_checkbox_id(self, name):
"""
Given the name of the delete checkbox input, return the HTML id for it.
"""
return 'id_' + name
def render(self, name, value, attrs=None):
substitutions = {}
template = '{input}'
substitutions['input'] = FileInput().render(name, value, attrs)
if value and hasattr(value, "url"):
template = self.template_with_initial
substitutions['initial'] = format_html(
self.url_markup_template,
value.url,
force_text(value)
)
checkbox_name = self.delete_checkbox_name(name)
checkbox_id = self.delete_checkbox_id(checkbox_name)
substitutions['delete'] = CheckboxInput().render(checkbox_name, False, attrs={'id': checkbox_id})
return mark_safe(template.format(**substitutions))