В формах inlineformset как я могу узнать, какие поля формы используются по умолчанию, а какие добавлены Django?

#django #django-forms

#django #django-forms

Вопрос:

У меня есть определенный набор форм (inlineformset), и я хочу внести некоторые изменения в дизайн по умолчанию.

Я выполняю цикл таким образом:

 {% for form in formset %}
    <div class="ct-formset">
        {% if form.errors %}<div>{{ form.errors }}</div>{% endif %}
        {% for field in form %}{{ field }}{% endfor %}

 {% endfor %}    
  

Для каждой формы Django добавляет два других поля — поле внешнего ключа и поле удаления.

Поскольку я хочу использовать один и тот же код для нескольких наборов форм, в цикле я не запрашиваю field by name

Мне нужно знать в:

  {% for field in form %}{{ field }}{% endfor %}
  

Как я могу узнать, какие поля формы используются по умолчанию, а какие добавлены Django?

Ответ №1:

При работе с экземпляром формы вы не можете точно сказать, какие поля добавлены изначально в классе или после создания экземпляра.

Хотя, здесь у вас есть несколько подходов к тому, как предотвратить отображение тех полей, которые вы не хотите отображать в результирующем наборе форм.

Если у вас есть доступ к классу формы …

… на данный момент вам нужно «отфильтровать», в каких полях находятся исходные поля такой формы, которые вы могли бы:

 >>> class MyForm(forms.Form):
>>>    title = forms.CharField()

>>> class_dict = vars(MyForm)

>>> class_dict['declared_fields']

OrderedDict([('title', <django.forms.fields.CharField at 0x7f496ce067d0>)])
  

О полях *-DELETE и *-ORDER

При работе с наборами форм вы должны учитывать, что не только Django может добавлять дополнительные поля в ваши формы, вы также можете это сделать.

Во-первых, мы должны понять, почему эти поля существуют.

Регистр для полей *-DELETE и *-ORDER добавляется только в том случае, если вы включаете их с помощью:

 formset = formset_factory(..., can_delete=True, can_order=True)
  

Django использует BaseFormSet.add_fields для добавления дополнительных полей, необходимых для упорядочивания или удаления, вы также можете использовать его для добавления своих собственных дополнительных полей.

Что вы можете сделать?

Вы можете просто передать False туда.

Интересный эксперимент …

Я провожу эксперимент, чтобы проиллюстрировать эффект, который может иметь перезапись этого:

 from django import forms

class MyForm(forms.Form):
    title = forms.CharField()

class MyBaseFormSet(forms.BaseFormSet):
    def add_fields(self, form, i):
        # Avoiding FormSets using this to add additional fields
        return form

# Create a form set with deletion and ordering enabled.
# pay attention to the argument: formset=MyBaseFormSet
MyFormSet  = forms.formset_factory(MyForm, formset=MyBaseFormSet, can_delete=True, can_order=True)

fs = MyFormSet()
for form in fs:
    print(form.as_table())
  

Результат: в результирующие формы не добавлены поля УДАЛЕНИЯ или упорядочивания.

 >>> <tr><th><label for="id_form-0-title">Title:</label></th><td><input type="text" name="form-0-title" id="id_form-0-title" /></td></tr>
  

Как насчет ForeignKey

Это то, что вы можете решить в формах. Если вы не хотите, ForeignKey чтобы они отображались, вы могли бы использовать forms.HiddenInput виджет для таких полей в ваших формах.

Также, если вы работаете с ModelForms, вы можете выбрать поля, которые будут использоваться для создания формы.

Заключение

С помощью этой информации, я надеюсь, вы сможете спланировать, как реализовать ваше требование о наличии общего шаблона для этих наборов форм.

Отправные точки:

  1. Передайте can_delete или / и start_order как False в formset_factory .
  2. Установите forms.HiddenInput виджет для полей ForeignKey в ваших формах.
  3. Найдите способ получить класс form и используйте vars, чтобы узнать исходные поля формы.
  4. Если вы используете ModelForms, используйте мета-конфигурацию fields или exclude , чтобы указать, какие поля используются для построения формы.