Django Formsets: сделать сначала требуется? - PullRequest
34 голосов
/ 09 марта 2010

Эти наборы форм показывают именно то поведение , противоположное , которое мне нужно.

Мой вид настроен так:

def post(request): # TODO: handle vehicle formset
    VehicleFormSetFactory = formset_factory(VehicleForm, extra=1)
    if request.POST:
        vehicles_formset = VehicleFormSetFactory(request.POST)
    else:
        vehicles_formset = VehicleFormSetFactory()

И мой шаблон выглядит так:

    <div id="vehicle_forms">
        {{ vehicles_formset.management_form }}
        {% for form in vehicles_formset.forms %}
            <h4>Vehicle {{forloop.counter}}</h4>
            <table>
                {% include "form.html" %}
            </table>
        {% endfor %}
    </div>

Таким образом, он изначально генерирует только 1 форму, как я хочу. Но я хочу, чтобы эта форма была обязательной!

Когда я динамически добавляю пустые формы с помощью JavaScript и vehicles_formset.empty_form, требуются все эти дополнительные формы, которые мне не нужны.

Из документов:

Форма достаточно умна, чтобы игнорировать дополнительные формы, которые не были изменены.

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

Есть ли какой-нибудь атрибут, который я могу изменить, чтобы сделать, по крайней мере, одну форму?

Ответы [ 4 ]

68 голосов
/ 10 февраля 2011

Нашли лучшее решение:

class RequiredFormSet(BaseFormSet):
    def __init__(self, *args, **kwargs):
        super(RequiredFormSet, self).__init__(*args, **kwargs)
        for form in self.forms:
            form.empty_permitted = False

Затем создайте свой набор форм следующим образом:

MyFormSet = formset_factory(MyForm, formset=RequiredFormSet)

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

Это сделает все необходимые формы. Вы можете сделать только первый требуемый, установив self.forms[0].empty_permitted в False.

25 голосов
/ 30 апреля 2015

Новое в Django 1.7: вы можете указать это поведение с помощью formset_factory

https://docs.djangoproject.com/en/1.8/topics/forms/formsets/#validate-min

VehicleFormSetFactory = formset_factory(VehicleForm, min_num=1, validate_min=True, extra=1)
10 голосов
/ 11 марта 2010

Ну ... это делает первую форму обязательной.

class RequiredFormSet(BaseFormSet):
    def clean(self):
        if any(self.errors):
            return
        if not self.forms[0].has_changed():
            raise forms.ValidationError('Please add at least one vehicle.') 

Единственная «проблема» состоит в том, что если существует 0 форм, то метод clean, кажется, вообще не вызывается, поэтому я не знаю, как проверить, есть ли 0. Действительно ... это никогда не должно происходить (за исключением того, что в моем JS есть ошибка, позволяющая удалить все формы).

2 голосов
/ 09 марта 2010

О, я думаю, я вижу. Попробуйте это:

from django.forms.formsets import BaseFormSet, formset_factory
class OneExtraRequiredFormSet(BaseFormSet):
    def initial_form_count(self):
        return max(super(OneExtraRequiredFormSet,self).initial_form_count() - 1,0)

VehicleFormSetFactory = formset_factory(VehicleForm, formset=OneExtraRequiredFormSet, extra=1)

== Оригинальный ответ ниже ==

Когда вы говорите «хотя бы сделайте одну форму обязательной», я предполагаю, что вы имеете в виду «сделать только одну дополнительную форму обязательной, независимо от того, сколько было добавлено с помощью javascript».

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...