/ / Django Management Form está falhando porque 'form-TOTAL_FORMS' e 'form-INITIAL_FORMS' não estão preenchidos corretamente - django, django-views, django-forms

O Formulário de Gerenciamento do Django está falhando porque 'form-TOTAL_FORMS' e 'form-INITIAL_FORMS' não estão preenchidos corretamente - django, django-views, django-forms

Em formação:

Eu gostaria de criar formulários aninhados como é melhor descrito por meio do exemplo fornecido em:

http://yergler.net/blog/2009/09/27/nested-formsets-with-django/

O tutorial nesta página parece ser muito bom e está tentando resolver o problema exato que estou encontrando.

Parece haver um problema com essa implementação no arquivo views.py quando não há dados de solicitação POST (ou seja, estamos realizando o preenchimento inicial do banco de dados).

O código pode ser visto na URL fornecida acima (se necessário, posso postar parte do código, mas temo que isso vá prejudicar as informações fornecidas aqui).

Aqui está o código views.py que está falhando (em negrito):

block = get_object_or_404(models.Block, id=block_id)

if request.method == "POST":
formset = forms.BuildingFormset(request.POST, instance=block)

if formset.is_valid():
rooms = formset.save_all()

return redirect("block_view", block_id=block.id)

else:
formset = forms.BuildingFormset(instance=block)  #This is the line that is throwing the ValidationError

A mensagem de erro que estou recebendo é:

ValidationError at "urlName":
[u"ManagementForm data is missing or has been tampered with"]

Eu cavei mais fundo e parece que essa falha está ocorrendo na linha site-packages / django / forms / formsets.py

o is_valid() a verificação está falhando porque alguns dos dados necessários do formulário de gerenciamento (form-TOTAL_FORMS, form-INITIAL_FORMS e form-MAX_NUM_FORMS) são inválidos. Aqui está a saída real de self.errors abaixo:

{u"TOTAL_FORMS": [u"This field is required."], u"INITIAL_FORMS": [u"This field is required."]}

Código:

edit_building.html:

{{buildings.management_form}}

{% para construção em edifícios.formas%}

 {{ building }}

{% if building.nested %}
{% for formset in building.nested %}
{{ formset.as_table }}
{% endfor %}
{% endif %}

{% endfor%}

views.py:

def should_delete(self, form):
"""Convenience method for determining if the form’s object will
be deleted; cribbed from BaseModelFormSet.save_existing_objects."""

if self.can_delete:
raw_delete_value = form._raw_value(DELETION_FIELD_NAME)
should_delete = form.fields[DELETION_FIELD_NAME].clean(raw_delete_value)
return should_delete

return False

def save_all(self, commit=True):
"""Save all formsets and along with their nested formsets."""

# Save without committing (so self.saved_forms is populated)
# — We need self.saved_forms so we can go back and access
#    the nested formsets
objects = self.save(commit=False)

# Save each instance if commit=True
if commit:
for o in objects:
o.save()

# save many to many fields if needed
if not commit:
self.save_m2m()

# save the nested formsets
for form in set(self.initial_forms + self.saved_forms):
if self.should_delete(form): continue

for nested in form.nested:
nested.save(commit=commit)

forms.py:

def should_delete(self, form):
"""Convenience method for determining if the form’s object will
be deleted; cribbed from BaseModelFormSet.save_existing_objects."""

if self.can_delete:
raw_delete_value = form._raw_value(DELETION_FIELD_NAME)
should_delete = form.fields[DELETION_FIELD_NAME].clean(raw_delete_value)
return should_delete

return False

def save_all(self, commit=True):
"""Save all formsets and along with their nested formsets."""

# Save without committing (so self.saved_forms is populated)
# — We need self.saved_forms so we can go back and access
#    the nested formsets
objects = self.save(commit=False)

# Save each instance if commit=True
if commit:
for o in objects:
o.save()

# save many to many fields if needed
if not commit:
self.save_m2m()

# save the nested formsets
for form in set(self.initial_forms + self.saved_forms):
if self.should_delete(form): continue

for nested in form.nested:
nested.save(commit=commit)

Notas:

Questões:

No caso de não haver dados POST e oo formulário está sendo gerado exclusivamente a partir do banco de dados, como os dados "form-TOTAL_FORMS" && "form-INITIAL_FORMS" devem ser preenchidos corretamente para solucionar esta falha?

Respostas:

4 para resposta № 1

Atualizar:

Depois de olhar através o exemplo você forneceu há um trecho que se lê assim em forms.py no final de add_fields() método:

# store the formset in the .nested property
form.nested = [
TenantFormset(data = self.data,
instance = instance,
prefix = "TENANTS_%s" % pk_value)
]

o data argumento está causando problemas porque é inicialmente vazio e internamente o Django irá determinar se um formulário está ligado por uma condicional semelhante a esta:

self.is_bound = data is not None

# Example
>>> my_data = {}
>>> my_data is not None
True

E como você pode ver um dicionário vazio em Python não é nenhum, então seu TenantFormset é tratado como um bound formulário, embora não seja. Você pode corrigi-lo com algo como o seguinte:

# store the formset in the .nested property
form.nested = [
TenantFormset(data = self.data if any(self.data) else None,
instance = instance,
prefix = "TENANTS_%s" % pk_value)
]

Você poderia postar a visão e o código do formulário, bem como o código do modelo para o seu formulário?

Meu palpite é que você não está usando o ‘management_form’ em seu modelo (que adiciona os campos “form-TOTAL_FORMS” e “form-INITIAL_FORMS” que estão faltando), ou seja,

<form method="post">
{{ formset.management_form }}
<table>
{% for form in formset %}
{{ form }}
{% endfor %}
</table>
</form>