formset встроенных formsets в django 1.3+

У меня есть модель продукта и модель цены. Ценовая модель имеет FK для модели продукта. Может быть несколько цен (в зависимости от количества проданных единиц). Предыдущая версия django 1.2.5 http://yergler.net/blog/2009/09/27/nested-formsets-with-django/ могла бы решить эту проблему. Но, как подробно http://www.mail-archive.com/django-users@googlegroups.com/msg124195.html это больше не работает.

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

Продукт Один - Цена Один, Количество - Цена Два, Количество Продукт Два - Цена Один, Количество Продукт Три - Цена Один, Количество - Цена Два, Количество - Цена Три, Количество

Воспроизведено для ясности:

В исходном коде Натана форма набора самого низкого уровня создается следующим образом:

TenantFormset(data=self.data,
              instance=instance,
              prefix='TENANTS_%s' % pk_value)

где instance - это экземпляр Building, "parent" или контейнер для арендаторов, а self - это экземпляр

class BaseBuildingFormset(BaseInlineFormSet)

который создается следующим образом:

BuildingFormset = inlineformset_factory(models.Block,
                                        models.Building,
                                        formset=BaseBuildingFormset,
                                        extra=1)

Чтобы обойти это, я перестал передавать self.data, что привело к тому, что формы на самом нижнем уровне всегда имели is_bound = False, даже после того, как они были отрисованы и отправлены обратно в представление. Следовательно, проверка всегда заканчивается неудачей, и объекты, которые представляют формы, не могут быть обновлены. Я воспроизвел поведение, используя код из поста Натана в блоге, поэтому кажется, что этот подход к вложению наборов форм больше не действителен, или код нуждается в настройке для работы на 1.3.

До Django 1.2.5 код Натана работает нормально. Однако в 1.3, если self.data передается в TenantFormset, он оказывается пустым, и возникает ошибка ValidationError, поскольку информация ManagementForm не была предоставлена.
Это предполагаемое последствие #11418, AFAICT.

Есть ли у кого-нибудь еще идеи о том, как это можно сделать?

Ура,

(Извините за отсутствие подробных примеров кода - пост Натана намного яснее, чем мой код, поэтому я рекомендую вам взглянуть на это.)

Общее примечание: кажется, что существует много путаницы относительно того, как это сделать, что показано в ответах здесь http://www.reddit.com/r/django/comments/hwyto/is_there_a_way_to_do_nested_formsets_in_django/

3 ответа

Как говорит django docs, необходимо передать data = None, если форма не связана:

data = None
if self.data:
    data = self.data
form.nested = [ModelXYFormset(data=data, instance = instance, prefix = 'opt%s' % pk_value)]

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

В BaseBuildingFormset:

def is_valid(self):
    result = super(BaseProtocolEventFormSet, self).is_valid()

    for form in self.forms:
        if hasattr(form, 'nested'):
            for n in form.nested:
                n.data = form.data
                if form.is_bound:
                    n.is_bound = True
                for nform in n:
                    nform.data = form.data
                    if form.is_bound:
                        nform.is_bound = True
                # make sure each nested formset is valid as well
                result = result and n.is_valid()
    return result

Данные для каждой формы и набора форм должны быть одинаковыми (полные данные POST). Здесь мы вручную устанавливаем это для форм, которые не получают его. Мы также можем видеть, что в классе BaseForm is_bound просто проверяет, что форма имеет данные или файлы, поэтому, как только в форме есть данные, мы устанавливаем для нее значение true.

Я сейчас пытаюсь сделать то же самое. Я реализовал то же решение из кода Натана, но столкнулся с ValidationError вопрос. В нашем Django 1.3 обновлено, как работают наборы форм, как показано здесь. Так что для моего кода,

TenantFormset(data=self.data, instance=instance, prefix='TENANTS_%s' % pk_value)

становится

TenantFormset(instance=instance, prefix='TENANTS_%s' % pk_value)

Но я все еще получаю чистую форму, хотя.

Другие вопросы по тегам