UpdateView清除已删除的表单但实际上并未将其删除

时间:2014-10-14 21:14:50

标签: django django-generic-views inline-formset imagefield

我有一个包含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

1 个答案:

答案 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))