Django 4 динамическое обновление полей формы с помощью HTMX

Я разработал Django приложение, в котором у меня есть форма с некоторыми полями. В зависимости от ввода дополнительные поля отображаются или скрываются. Сейчас в Django 3.2.14 все работало нормально, после обновления в Django 4.0.6 перестало работать.

Сначала я создаю форму, где если существует "field_rule_display", виджет поля устанавливается как "HiddenInput".

class AnalysisForm(forms.Form):
    def __init__(self, analysis_form_template: AnalysisFormTemplate, disable_required: bool, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.helper = FormHelper()
        self.helper.layout = Layout()
        self.helper.add_input(Submit("submit", _("Evaluate"), css_class="btn-primary btn-lg"))
        analysis_field_queryset = analysis_form_template.analysis_fields
        analysis_form_url = reverse("analysis_form", args=(analysis_form_template.id,))
        for field in analysis_field_queryset.all():
            htmx_dictionary = _htmx_dictionary(analysis_form_url, field)
            self.fields[field.name_for_formula] = _get_field_by_type(
                field, htmx_dictionary, analysis_form_template, self.data
            )
            self.fields[field.name_for_formula].empty_values = empty_values()
            self.helper.layout.fields.append(
                Div(Field(field.name_for_formula), css_class=AnalysisFieldKind(field.kind).name)
            )
            if field.field_rule_display is not None and disable_required is False:
                self.fields[field.name_for_formula].widget = forms.HiddenInput()
                self.fields[field.name_for_formula].widget.attrs["disabled"] = True
            if disable_required:
                self.fields[field.name_for_formula].required = False

После того, как пользователь введет в форму определенные данные, htmx отправит запрос, и я перестрою форму с новыми полями. И здесь начинается проблема, даже если я обновляю свое поле в "self.fields" Django не отображает обновление и поле моей формы остается скрытым.

            if field.field_rule_display is not None:
                evaluated_result_display = self._evaluated_formula(
                    field,
                    analysis_form_template,
                    field.field_rule_display,
                    field.field_rule_display.formula,
                    cleaned_data,
                )
                if evaluated_result_display:
                    field_type = _get_field_by_type(
                        field, htmx_dictionary, analysis_form_template, cleaned_data
                    )
                    self.fields[field.name_for_formula] = field_type
                    self.fields[field.name_for_formula].initial = cleaned_data[field.name_for_formula]

enter image description here

Здесь должно отображаться второе поле, но в результате изменения помощника crispy layout отображается только моя граница. enter image description here

            if (
                field.field_rule_display is None or (field.field_rule_display is not None and evaluated_result_display)
            ) and field.field_rule_highlight is not None:
                evaluated_result_highlight = self._evaluated_formula(
                    field.name_for_formula,
                    analysis_form_template,
                    field.field_rule_highlight,
                    field.field_rule_highlight.formula,
                    cleaned_data,
                )
                if evaluated_result_highlight:
                    field_layout = Div(
                        Field(field.name_for_formula),
                        css_class=f"{AnalysisFieldKind(field.kind).name} border border-primary mb-2 p-2",
                    )
            self.fields[field.name_for_formula].empty_values = empty_values()
            field_layout_list.append(field_layout)
        self.helper.layout.fields = field_layout_list

Буду признателен за помощь, почему это больше не работает в Django 4, а в Django 3 работало без проблем.

Большое спасибо.

После некоторой отладки я нашел возможное решение моей проблемы.

Похоже, что Django кэширует поля моей формы и их виджеты в "_bound_fields_cache". Теперь там виджет моих полей все еще имеет значение "HiddenInput", даже после обновления виджета на "TextInput".

enter image description here enter image description here

Поэтому я попробовал обновить поле в "_bound_fields_cache" и, к моему удивлению, оно сработало.

            if field.field_rule_display is not None:
                evaluated_result_display = self._evaluated_formula(
                    field,
                    analysis_form_template,
                    field.field_rule_display,
                    field.field_rule_display.formula,
                    cleaned_data,
                )
                if evaluated_result_display:
                    field_type = _get_field_by_type(
                        field, htmx_dictionary, analysis_form_template, cleaned_data
                    )
                    self.fields[field.name_for_formula] = field_type
                    self.fields[field.name_for_formula].initial = cleaned_data[field.name_for_formula]
                    if field.name_for_formula in self._bound_fields_cache:
                        self._bound_fields_cache[field.name_for_formula].field = field_type

enter image description here enter image description here

Но я не совсем удовлетворен таким решением. Я не могу точно сказать, почему Django не изменяет "_bound_fields_cache" после обновления полей формы. Изменение "_bound_fields_cache" кажется мне уродливым хаком... Возможно, есть лучшее решение?

Вернуться на верх