Django 通用表单集 ManytoManyField 不是清理数据的一部分

Django generic formset ManytoManyField not part of cleaned data

我的表单集基于 CRUD 方法。从这里和那里获取代码。现在的问题是我无法保存模型,没有调用 form_valid 方法。 模板如下所示:

<form action="create" method=”POST”>
    {% csrf_token %}
    <div id="formset" data-formset-prefix="{{ formset.prefix }}">
        {{ formset.management_form }}
        <div data-formset-body>
            {% for form in formset %}
            <div data-formset-form>
                {{ form }}                
            </div>
            {% endfor %}
            <hr>
        </div>
</form>

其所基于的Formsetclass如下:

class Formset(LayoutObject):
    template = "doc_aide/formset2.html"

    def __init__(self, formset_name_in_context, template=None):
        self.formset_name_in_context = formset_name_in_context
        self.fields = []
        if template:
            self.template = template

    def render(self, form, form_style, context, template_pack=TEMPLATE_PACK):
        formset = context[self.formset_name_in_context]
        # for form in formset:
        return render_to_string(self.template, {'formset': formset})

表单和视图如下:

class PrescriptionForm(forms.ModelForm):
    class Meta:
        model = Prescription
        exclude = ['handed_out', ]

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.helper = FormHelper()
        self.helper.form_tag = True
        self.helper.form_class = 'form-horizontal'
        self.helper.label_class = 'col-md-3 create-label'
        self.helper.field_class = 'col-md-9'
        self.helper.layout = Layout(
            Div(
                Field('patient'),
                Field('note'),
                HTML('<hr class="style2">'),
                Fieldset('Add Drug', Formset('line_prescription')),
                HTML('<hr class="style1">'),
                ButtonHolder(Submit('submit', 'save')),
                )
            )

    def clean(self, *args, **kwargs):
        cleaned_data = super().clean(*args, **kwargs)
        print(cleaned_data)
        # cleaned_data.get('line_prescription')
        return cleaned_data


class PrescriptionCreate(generic.CreateView):
    model = Prescription
    template_name = 'doc_aide/write_prescription4.html'
    form_class = PrescriptionForm
    
    def get_context_data(self, **kwargs):
        print('here')
        context = super().get_context_data(**kwargs)
        if self.request.POST:
            context['line_prescription'] = SinglePrescriptionFormset(self.request.POST)
        else:
            context['line_prescription'] = SinglePrescriptionFormset()
        context['form'].fields['patient'].initial = Patient.objects.get(pk=self.kwargs['patient'])
        return context

    def form_valid(self, form):
        print('Ia am here')
        context = self.get_context_data()
        prescriptionlines = context['line_prescription']
        with transaction.atomic():
            form.instance.created_by = self.request.user
            self.object = form.save()
            if prescriptionlines.is_valid():
                prescriptionlines.instance = self.object
                prescriptionlines.save()
        return super().form_valid(form)

    def get_success_url(self):
        return reverse_lazy('doc_aide:prescription_detail', kwargs={'pk': self.object.pk})

到目前为止我发现验证失败。因为 line_prescription 不是清理数据的一部分。

{'patient': <Patient: HF-1_2020>, 'no_charge': False, 'note': '-'}

如何使 Formset 数据成为清理数据的一部分?

ManyToManyField 需要是可选字段。所以在模型中添加 blank=True 就可以了。