Django formset - показывать дополнительные поля только тогда, когда не заданы начальные данные?

У меня есть страница с несколькими наборами форм, каждая из которых имеет префикс. Форматы создаются с использованием formset_factory параметров по умолчанию, включая extra=1. Строки можно добавлять или удалять с помощью JavaScript.

Если пользователь добавляет новые данные, появляется одна пустая строка. Совершенная.

Если пользователь добавил данные, но проверка формы не прошла, в этом случае набор форм заполняется данными POST с использованием MyFormset(data, prefix='o1-formsetname') и т.д., появляются только данные, которые они ввели. Опять же, отлично. (o1 и т.д. динамически генерируются, каждый o соответствует "опции", и каждая "опция" может иметь несколько форм).

Однако, если пользователь редактирует существующие данные, в этом случае представление заполняет набор форм с помощью MyFormset(initial=somedata, prefix='o1-formsetname'), где somedata - это список данных данных, которые поступают из модели в базе данных, добавляется дополнительная пустая строка после этих данных. Я не хочу, чтобы пустая строка появлялась, если пользователь явно не добавил ее с помощью JavaScript.

Есть ли какой-либо простой способ предотвратить появление набора форм в дополнительной строке, если установлены исходные данные? Причина, по которой я использую initial в третьем примере, заключается в том, что если бы я просто передал данные при использовании MyFormset(somedata, prefix='o1-formsetname'), мне пришлось бы сделать дополнительный шаг по переформатированию всех данных в файл стиля POSTdata, включая префиксы для каждого поля, например o1-formsetname-1-price: x и т.д., а также вычисление данных формы управления, что добавляет всю нагрузку осложнений.

Одним из решений может быть перехват набора форм перед его отправкой в ​​шаблон и вручную удалить строку, но атрибут extra_forms, похоже, не доступен для записи, а установка extra на 0 не делает никаких разница. Я также мог бы JavaScript обнаружить этот случай и удалить строку. Однако я не могу не думать о том, что мне не хватает чего-то очевидного, поскольку поведение, которое я хочу, - это то, что казалось бы разумным ожидаемым поведением для меня.

Спасибо.

Ответ 1

Я придумал решение, которое работает с Django 1.1. Я создал подкласс BaseFormSet, который переопределяет метод total_form_count таким образом, что если исходные формы существуют, то сумма не включает дополнительные формы. Возможно, бит взлома, и, возможно, там лучшее решение, которое я не смог найти, но он работает.

class SensibleFormset(BaseFormSet):
    def total_form_count(self):
        """Returns the total number of forms in this FormSet."""
        if self.data or self.files:
            return self.management_form.cleaned_data[TOTAL_FORM_COUNT]
        else:
            if self.initial_form_count() > 0:
                total_forms = self.initial_form_count()
            else:
                total_forms = self.initial_form_count() + self.extra
            if total_forms > self.max_num > 0:
                total_forms = self.max_num
            return total_forms

Ответ 2

Используйте аргумент ключевого слова max_num для formset_factory:

MyFormset = formset_factory([...], extra=1, max_num=1)

Подробнее см. ограничение максимального количества форм.

Одна задержка: предположительно вы хотите обрабатывать более одной пустой формы. Это не слишком сложно; просто убедитесь, что вы не используете аргумент ключевого слова max_num на стороне обработки POST.