2015-03-11 2 views
1

Я пытаюсь выполнить ответ, заданный @qris в предыдущем вопросе (django crispy forms: Nesting a formset within a form), но я получаю KeyError в formset = context[self.formset_name_in_context] в функции рендеринга. Я не совсем понимаю, что происходит. Откуда возникает контекст? Как я могу это исправить?Формы в форме с использованием хрустящих форм django

В forms.py я создаю formset для моего AuthorForm:

AuthorFormSet = formset_factory(AuthorForm) 
author_formset = AuthorFormSet() 

, а затем я использую author_formset в макете моей другой формы:

self.helper.layout = Layout(
    Div(
     Div('place', 'sample', css_class='col-xs-6'), 
     Div('subject_type', 'data_title', css_class='col-xs-6'), 
     css_class='row' 
    ), 
    MultiField(
     "Authors", 
     Formset('author_formset'), 
    ) 
) 

Моей последнюю попытку в в представлениях .py:

class register(TemplateView): 

    form_class = RegistrationForm() 
    facility_form = FacilityAndContactForm() 

    formsets = { 
     'author_formset': AuthorFormSet, 
    } 

    template_name = "databank/depositors.html" 

    def __init__(self, data, files, *args, **kwargs): 
     super(register, self).__init__(data, files, *args, **kwargs) 
     if 'initial' in kwargs: 
      # Formsets treat this parameter completely differently: they 
      # expect an array of values instead of just one. So remove it 
      # because it will break formsets. 
      kwargs.pop('initial') 

     for name, formset_class in self.formsets.iteritems(): 
      # doesn't exist yet, so we can't call its queryset() method 
      queryset = formset_class.model._default_manager.filter(
       **{formset_class.fk.name: self.instance}) 
      extra = 0 if queryset.exists() else 1 

      formset = self.construct_formset(formset_class, data, files, *args, prefix=name, extra=extra, **kwargs) 
      setattr(self, name, formset) 

      helper = getattr(formset.form(), 'helper', None) 
      if helper: 
       formset.helper = helper 

    def construct_formset(self, formset_class, data, files, prefix, extra, 
      *args, **kwargs): 
     return formset_class(data, files, *args, prefix=prefix, extra=extra, 
      **kwargs) 

    def get(self, request, *args, **kwargs): 
     form_class = self.form_class 
     return render(request, self.template_name, {'form_class': form_class, 
      'facility_form': self.facility_form, 'author_formset': 
      self.formset}) 

    def post(self, request): 
     form_class = RegistrationForm(request.POST, request.FILES) 
     facility_form = FacilityAndContactForm(request.POST) 

     author_formset=AuthorFormSet(request.POST) 
     formsets = { 
      'author_formset': author_formset, 
     } 

     if form_class.is_valid(): 
      registration = create_registration(form_class) 
      dataset_name = registration.dataset.dataset_name 
      # more logic here... 

     return render(request, 'databank/register.html', 
      {'registration_form': form_class, 'facility_form': facility_form, 
      'author_formset': author_formset}) 
+0

@qris где/как я сначала объявить объект макета, чтобы перейти к новому Formset поле? В вашем примере реализации, где/как вы вначале отказались от «сокращения»? – steph

ответ

1

Вы сами должны вставить author_formset в контекст :) Этого не может быть там другой путь.

Это, как я обобщил сам, имея dict автоматическ возведенных суб- formsets на моей форме:

class MyForm(ModelForm): 
    formsets = { 
     'author_formset': AuthorFormSet, 
    } 

    def __init__(self, data, files, *args, **kwargs): 
     super(MyView, self).__init__(data, files, *args, **kwargs) 
     if 'initial' in kwargs: 
      # Formsets treat this parameter completely differently: they 
      # expect an array of values instead of just one. So remove it 
      # because it will break formsets. 
      kwargs.pop('initial') 

     for name, formset_class in self.formsets.iteritems(): 
      # doesn't exist yet, so we can't call its queryset() method 
      queryset = formset_class.model._default_manager.filter(
       **{formset_class.fk.name: self.instance}) 
      extra = 0 if queryset.exists() else 1 

      formset = self.construct_formset(formset_class, data, files, *args, 
       prefix=name, extra=extra, **kwargs) 
      setattr(self, name, formset) 

      helper = getattr(formset.form(), 'helper', None) 
      if helper: 
       formset.helper = helper 

    def construct_formset(self, formset_class, data, files, prefix, extra, 
      *args, **kwargs): 
     return formset_class(data, files, *args, prefix=prefix, extra=extra, 
      **kwargs) 
+0

Большое вам спасибо за помощь! @qris Я никогда не использовал Class Based Views до этого, честно говоря, я все еще очень смущен. (Я сейчас читаю их, пытаясь понять). Есть ли способ сделать это с помощью функциональных представлений? Или, если я напишу больше о том, что я сейчас/пытаюсь, не могли бы вы мне помочь? – steph

+0

Я добавил свою последнюю попытку просмотра, но я получаю ошибки в том, что не передаю правильные параметры init. __init __() принимает не менее 3 аргументов (1 задано) ' – steph

+0

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

Смежные вопросы