Django: ManagementForm 数据丢失...表单集将无法验证。为什么?

发布于 2024-10-10 22:53:06 字数 5344 浏览 6 评论 0原文

由于某种原因,我提交后,我的表单集将无法验证。关于这可能发生的方式有什么想法吗?

#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>

跟进(解决方案):

Brant 提供了一些关于错误发生原因的见解。对于我的情况,他的洞察力帮助我构建了一个更适合我的情况的黑客。此技巧似乎适用于可能已在模板内以某种方式修改的表单集。就我而言,我的表单集变得复杂,需要一些 ajax 来使其更加用户友好。

“retrieve_provider_instance(email)”是一种根据数据库中设置的各种标准检索提供者对象的动态方法(大约 200 行代码)。

经过一些广泛的调试后,以下黑客对我有用。我通过在模板的“for”循环中添加以下隐藏字段解决了这个问题。

{% {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 %} 

我接受了马克的回答,因为它更适用于我提出的具体问题。希望这对将来尝试实现此示例的其他用户有所帮助。事实上,在提交时分配“前缀”是正确的方法,也是最有意义的。

感谢您的所有回复。

此致, Matt


后续:我想我可能已经找到了部分问题。但是,事情还没有解决。

以下是一些可能有助于解决问题的附加信息。 不正确的 POST 数据是否会造成这种情况?如果是这样,我该如何解决这个问题?

这是我提交表单集后发生的情况(在本例中只有一个表单):

回溯如下:

_management_form 中的文件“/home/mhjohnson/webapps/resourcedb/lib/python2.6/django/forms/formsets.py” 68. raise 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'....'

有什么想法吗?

For some reason my formset will not validate, after I submit it. Any ideas as to way this may be happening?

#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>

Follow up (solution):

Brant offered gave some insight into why the error was occurring. For my case, his insight helped me construct a hack that worked better for my situation. This hack seems applicable for a formsets that may have been modified in a certain way within the template. In my case, my formset became complicated and required some ajax to make it more user friendly.

The "retrieve_provider_instance(email)" was a dynamic way of retrieving the provider object based on various criteria set in the database (about 200 lines of code vomit).

The following hack worked for me, after some extensive debugging. I solved it by adding this the following hidden field in my template's "for" loop

{% {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 %} 

I accepted Mark's answer, because it was much more applicable for the specific question I was asking. Hopefully, this will help other users in the future who try to implement this example. Indeed, assigning the 'prefix' on submit is the correct way and makes the most sense.

Thank-you for all of your responses.

Best Regards,
Matt


Follow-up: I think I may have found part of my problem. But, it is not solved yet.

Here is some additional information that may help solve the problem. Could incorrect POST data be messing this up? And if so, how do I work around this?

This is what happens after I submit the formset (in this case there is only one form):

Traceback is as follows:

File "/home/mhjohnson/webapps/resourcedb/lib/python2.6/django/forms/formsets.py" in _management_form
68. raise ValidationError('ManagementForm data is missing or has been tampered with')

This is my POST data:

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'....'

Any ideas?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

洋洋洒洒 2024-10-17 22:53:06

您的问题在这里:

       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 中,则传递“department”前缀。但是,当“提交”位于 POST 中时,您无需传递前缀。如果没有前缀,表单集无法在 POST 中找到正确的数据。

Your problem is here:

       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)

If there is no POST you pass a prefix of 'department'. If 'add_department' is in the POST you pass the prefix of 'department'. However when 'submit' is in the POST you do not pass the prefix. Without the prefix the formset cannot find the proper data in the POST.

请止步禁区 2024-10-17 22:53:06

有两件事引起了我的注意……

首先,您不需要执行这部分:

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''

Two things jump out at me...

First, you shouldn't need to do this part:

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

That's taken care of when you do this:

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

Second, your code at the top:

provider_obj = retrieve_provider_instance(email)

May not be working. In the traceback you provided, it doesn't look like the provider is getting there...

department-0-provider -----> u''
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文