Django: данные ManagementForm отсутствуют... Formset не будет проверяться. Зачем?

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

# models.py

class Department(models.Model):
  department = models.CharField(verbose_name = "Department Name", max_length=100)
  description = models.TextField(verbose_name = "Description", blank=True, null=True)
  sp_description = models.TextField(verbose_name = "Description (Spanish)", blank=True, null=True)
  phone = PhoneNumberField()
  phone_ext = models.CharField(max_length=10, blank=True)

  #Relations
  provider = models.ForeignKey(Provider, blank=True, null=True)
  services_offered = models.ManyToManyField(ServiceType)

  def __unicode__(self):
    return self.department

# view.py

def display_step5(request):
    msg = ''
    email = request.session.get('email')
    provider_obj = retrieve_provider_instance(email)
    AddDepartmentFormSet = inlineformset_factory(Provider, Department, extra=0)
    if is_authenticated(request):
        AddDepartmentFormSet = inlineformset_factory(Provider, Department, extra=0)
        if request.method=='POST':
            if 'add_department' in request.POST:
                cp = request.POST.copy()
                cp['department-TOTAL_FORMS'] = int(cp['department-TOTAL_FORMS'])+ 1
                new_department = AddDepartmentFormSet(cp, prefix='department', instance=provider_obj)
            elif 'submit' in request.POST:
                formset = AddDepartmentFormSet(request.POST, instance=provider_obj)
                instances = formset.save(commit=False)
                for instance in instances:
                    instance.provider = provider_obj
                    instance.save()
                return HttpResponse("Departments have been added")
        else:
            new_department = AddDepartmentFormSet(prefix='department', instance=provider_obj)

    else:
        return HttpResponseRedirect(reverse('health.register.views.display_auth'))
    return render_to_response('step5-test.html',
{'department': new_department}, context_instance=RequestContext(request))

step5-test.html

<form method='post' action='{{request.path}}'>{% csrf_token %}
  <fieldset>
    <legend>Departments</legend>
      {{ department.management_form }}
      {% for form in department.forms %}
        <HR> <div><table>{{form.as_table}}</table></div>
      {% endfor %}
     <BR/> 
     <input title='Add a new department' type='submit' name='add_department' value='Add-Another-Department' />
    </fieldset>
    <BR/><BR/>
    <input title='Submit this form' type='submit' name='submit' value='Submit' />
</form>

Продолжение (решение):

Предложенный Брант дал некоторое представление о том, почему произошла ошибка. Для моего случая его понимание помогло мне создать хак, который работал лучше для моей ситуации. Этот хак кажется применимым для наборов форм, которые могли быть изменены определенным образом в шаблоне. В моем случае мой набор форм усложнился и потребовал некоторого Ajax, чтобы сделать его более удобным для пользователя.

"Retrieve_provider_instance(email)" был динамическим способом получения объекта провайдера на основе различных критериев, установленных в базе данных (около 200 строк кода рвота).

Следующий взлом сработал для меня после некоторой обширной отладки. Я решил это, добавив следующее скрытое поле в цикле "для" моего шаблона

{% {for form in formset.forms %}
                     <tr>
                      <td>
                         {% if form.instance.pk %} <!--- if instance already exists on db --->  
                         {{ form.DELETE }}
                         <input type='hidden' name="department_set-{{ forloop.counter0 }}-id" id="id_department_set-{{ forloop.counter0 }}-id"  value={{ form.instance.pk }} />
                         {% endif %}
                      Name: <br/> {{ form.department}} <br/>
                      Phone Number: <br/> {{ form.phone }} <br/>
                      Phone Ext: <br/> {{ form.phone_ext }}</td>
                      <td>Description: <br/> {{ form.description }}</td>
                      <td>Description (Spanish): <br/> {{ form.sp_description }}</td>
                      <td>Services Provided: <br/> {{ form.services_offered }}</td>
                      <td></td>
                   </tr>
                   {% endfor %} 

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

Спасибо за все ваши ответы.

С наилучшими пожеланиями, Мэтт


Продолжение: я думаю, что, возможно, нашел часть моей проблемы. Но это еще не решено.

Вот некоторая дополнительная информация, которая может помочь решить проблему. Неправильные данные POST могут испортить это? И если так, как мне обойти это?

Вот что происходит после того, как я отправляю набор форм (в данном случае есть только одна форма):

Traceback выглядит следующим образом:

Файл "/home/mhjohnson/webapps/resourcedb/lib/python2.6/django/forms/formsets.py" в _management_form 68. повысить ValidationError("Данные ManagementForm отсутствуют или были подделаны")

Это мои данные POST:

department-0-phone_ext -----> u'222'

department-0-id -----> u''

department-0-services_offered -----> u'2'

department-0-phone -----> u'222-222-2222'

department-INITIAL_FORMS -----> u'0'

submit -----> u'Submit'

department-MAX_NUM_FORMS -----> u''

department-0-department -----> u'Test 1'

department-0-provider -----> u''

department-TOTAL_FORMS -----> u'1'

csrfmiddlewaretoken -----> u'92a39322b16ed7e5e10dbd6c5ac64bf4'

department-0-description -----> u'Blah blah'

department-0-sp_description -----> u'....'

Есть идеи?

2 ответа

Решение

Ваша проблема здесь:

       if request.method=='POST':
            if 'add_department' in request.POST:
                cp = request.POST.copy()
                cp['department-TOTAL_FORMS'] = int(cp['department-TOTAL_FORMS'])+ 1
                new_department = AddDepartmentFormSet(cp, prefix='department', instance=provider_obj)
            elif 'submit' in request.POST:
                formset = AddDepartmentFormSet(request.POST, instance=provider_obj)
                instances = formset.save(commit=False)
                for instance in instances:
                    instance.provider = provider_obj
                    instance.save()
                return HttpResponse("Departments have been added")
        else:
            new_department = AddDepartmentFormSet(prefix='department', instance=provider_obj)

Если POST отсутствует, вы передаете префикс "отдел". Если "add_department" находится в POST, вы передаете префикс "отдела". Однако, когда 'submit' находится в POST, вы не передаете префикс. Без префикса formset не может найти правильные данные в POST.

Две вещи прыгают на меня...

Во-первых, вам не нужно делать эту часть:

for instance in instances:
   instance.provider = provider_obj
   instance.save()

Это позаботится о том, когда вы делаете это:

formset = AddDepartmentFormSet(request.POST, instance=provider_obj)

Во-вторых, ваш код вверху:

provider_obj = retrieve_provider_instance(email)

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

department-0-provider -----> u''
Другие вопросы по тегам