2015-04-30 3 views
1

Кто-нибудь знает, почему это приводит к потере данных ManagementForm, когда я использую Formset Prefix?Данные ManagementForm отсутствуют при использовании префикса Formset

От Shell

>>> from django import forms 
>>> from django.forms.formsets import formset_factory 
>>> 
>>> class CheckBox (forms.Form): 
...  overwrite = forms.BooleanField (required = False) 
... 
>>> 
>>> data = { 
...  'form-TOTAL_FORMS': '2', 
...  'form-INITIAL_FORMS': '0', 
...  'form-MAX_NUM_FORMS': '3', 
...  'checkbox-0-overwrite': True, 
...  'checkbox-1-overwrite': False, 
... } 
>>> 
>>> CheckBoxFormSet = formset_factory (CheckBox) 
>>> formset = CheckBoxFormSet (data) 
>>> formset.is_valid() 
True 
>>> formset.cleaned_data 
[{}, {}] 
>>> 

Добавление префикса к Formset

>>> formset = CheckBoxFormSet (data, prefix = 'checkbox') 
>>> formset.is_valid() 
Traceback (most recent call last): 
    File "<console>", line 1, in <module> 
. 
. 
. 
django.core.exceptions.ValidationError: ['ManagementForm data is missing or has been tampered with'] 

Джанго Doc упоминается использовать префикс для различения между различными formset в 'а' зрения. Это применимо, если я использую его в одном представлении, но в другом методе, который обрабатывает другую HTML-страницу, например, пример? Выполнение того, что предложил Django в этом примере, также привело к тому, что данные ManagementForm были потеряны.

Например:

forms.py

class NodeForm (forms.Form): 

    cars = forms.CharField (required = False) 
    trucks = forms.CharField (required = False) 

class CheckBox (forms.Form): 
    overwrite = forms.BooleanField (required = False) 

views.py

def cars (request): 

    CarsFormSet = formset_factory (CarsForm, formset = BaseNodeFormSet, extra = 2, max_num = 5) 

    if request.method == 'POST': 

     cars_formset = CarsFormSet (request.POST, prefix = 'carsform') 

     if cars_formset.is_valid(): 
      data = cars_formset.cleaned_data 

      context = {'data': data} 
      return render (request, 'vehicleform/response.html', context) 
     else: 
      cars_formset = CarsFormSet (prefix = 'carsform') 

    context = {...previously entered data from POST...} 

    return render (request, 'vehicleform/carsform.html', context) 

def trucks (request): 

    TrucksFormSet = formset_factory (TrucksForm, extra = 2, max_num = 5) 

    if request.method == 'POST': 

     trucks_formset = TrucksFormSet (request.POST, prefix = 'trucksform') 

     if trucks_formset.is_valid(): 
      data = truck_formset.cleaned_data 

      context = {'data': data} 
      return render (request, 'vehicleform/success.html', context) 

     else: 
      trucks_formset = TrucksFormSet (prefix = 'trucksform') 

    return HttpResponse ('No overwrite data.') 

Update 1
Я сузил к фактическим данным. По некоторым причинам мне не нравятся мои данные.

Update 2
Я проверял и имя в форме и данные идентичны. Он печатает только один checkbox-0-overwrite, в то время как я указал 2 в своих данных. Интересно, почему набор форм не работал для флажка.

>>> CheckBoxFormSet = formset_factory (CheckBox) 
>>> formset = CheckBoxFormSet (prefix = 'checkbox') 
>>> 
>>> for form in formset: 
...  print (form) 
... 
<tr><th><label for="id_checkbox-0-overwrite">Overwrite:</label></th><td><input id="id_checkbox-0-overwrite" name="checkbox-0-overwrite" type="checkbox" /></td></tr> 
>>> 

Update 3
Я не уверен, что происходит больше. Это, по-видимому, порождает формы без префикса. Все еще получаю ошибку, когда вставляю префикс.

>>> CheckBoxFormSet = formset_factory (CheckBox) 
>>> formset = CheckBoxFormSet (data) 
>>> formset.is_valid() 
True 
>>> for form in formset: 
...  print (form) 
... 
<tr><th><label for="id_form-0-overwrite">Overwrite:</label></th><td><input id="id_form-0-overwrite" name="form-0-overwrite" type="checkbox" /></td></tr> 
<tr><th><label for="id_form-1-overwrite">Overwrite:</label></th><td><input id="id_form-1-overwrite" name="form-1-overwrite" type="checkbox" /></td></tr> 
>>> 
>>> 
>>> data { 
... 'form-TOTAL_FORMS': '2', 
... 'form-INITIAL_FORMS': '0', 
... 'form-MAX_NUM_FORMS': '3', 
... 'checkbox-0-overwrite': True 
} 

Update 4
HTML-шаблон ниже генерируется и создана первая форма, автомобили, как я обновил из приведенного выше примера. Вторая форма, которая только устанавливает флажки рядом с данными, передаваемыми первой формой. Отображение формы в шаблоне и нажатие кнопки «Отправить» все еще дают мне ошибку «ManagementForm». Я попытаюсь создать совершенно новую форму с только галочкой, чтобы узнать, не вызывает ли это каких-либо ошибок.

Response.html

<!DOCTYPE html> 
<html xmlns="http://www.w3.org/1999/html"> 
<head lang="en"> 
    <meta charset="UTF-8"> 
    {% load staticfiles %} 
    <link rel="stylesheet" type="text/css" href="{% static 'nodeform/style.css' %}" > 
    <title>Vehicle Information</title> 
</head> 
<body> 
    <h1>Vehicle Information:</h1> 
    <h4>Location: {{ location }}</h4> 
    <form action="trucks" method="POST">{% csrf_token %} 
    {{ checkbox_formset.management_form }} 
     {% for form in checkbox_formset %} 
     {{ form }} 
     {% endfor %} 
    <br> 
    <p><input type="submit" value="Confirm"> 
    <a href="{% url 'carsform' %}"> 
     <button type="button">Cancel</button></a></p> 
    </form> 
</body> 
</html> 

Update 5
Я не уверен, если я правильно понимаю, но я думаю, что неудача в действии форме и как я могу получить данные. Исходная форма (carsform.html) имел форму тег без действия:

carsform.html

<form action="" method="POST">{% csrf_token %}...</form> 

Это выполнить POST, а затем передать информацию, собранную на следующую страницу/форма (response.html).Кроме того, он добавляет formset флажков с предыдущими данными, как так:

response.html

<form action="trucks" method="POST">{% csrf_token %}...</form> 

Выход:

Audi (Obtained from cars) [] <---Checkbox inserted from response.html manually & obtaining data from method trucks 
Toyota (Obtained from cars) [] <---Checkbox inserted from response.html manually & obtaining data from method trucks 

Когда пользователь нажмите "Отправить", то response.html форма затем обработает и снова вернется обратно к грузовикам. На этот раз без данных из метода автомобилей обрабатывать. В результате это привело к ошибке ManagementForm.

Я протестировал это, вставив 2 формы на начальную страницу (carsform.html) и нажмите «Отправить». Результат, который я вижу на следующей странице/форме (response.html), имеет как данные первого, так и второго набора форм.

Мой следующий вопрос: как создать вторую форму (response.html) для получения данных без ошибки?

+0

Ну, часть проблемы, с которой я сталкиваюсь, заключается в том, что вы не публиковали именно то, что пытались сделать в первую очередь. Почему вы забираете кого-то на совершенно новую страницу, чтобы проверить поле, почему бы не поместить все на одну страницу и отправить данные формы один раз? – onyeka

+0

Я не хотел путать и пугать людей своей длинной целью, поэтому мне пришлось сузить до определенной проблемы. Причиной не помещать все на одну страницу является то, что форма должна проверять и обрабатывать ввод пользователя, чтобы определить, существует ли дублирование. Если есть, предоставьте пользователю возможность проверить и подтвердить перезапись или полностью игнорировать ее. Если у вас есть лучший способ сделать это, я бы хотел это услышать. Я ценю вашу помощь до сих пор. – dreamzboy

+0

Хм, хорошо, поэтому флажок предназначен для подтверждения подтверждения перезаписи, не так ли? Рассматривали ли вы использование JS для проверки дубликатов перед отправкой пользователем? Я также думаю о мастере, но это зависит от того, сколько полей вы хотите проверить на дубликаты, я думаю. – onyeka

ответ

2

Проблема заключается в методе автомобилей рендеринга на страницу response.html и отображающих обработанную форму на URL http://..../vehicle/cars вместо транспортных средств/грузовиков. «Ошибка формы управления» была поднята из-за того, что «POST» произошел второй раз, в то время как все еще в форме автомобиля/автомобиля url, а не в форме транспортных средств/грузовиков. Обновленный 5 намекнул на проблему. Решение состоит в том, чтобы просто использовать

return HttpResponseRedirect ('trucks') 

или

render (request, 'vehicleform/trucksform.html', context) 
return HttpResponseRedirect ('trucksform') 

разница между 2 выше, является первым решением, делает данные из второй формы (trucksform) в то время как второе решение делает данные из первая форма (carsform).

Почему это такое большое дело? Хорошо, потому что я хотел, чтобы первая форма снова отображалась без перенаправления на другую страницу, если есть ошибки; следовательно,

<form action="" method="POST"> 

В противном случае установка

<form action="truck" method="POST"> 

бы не создал этот беспорядок.

Чтобы иметь возможность использовать 2 разных набора форм в одном представлении, проверьте каждую страницу/форму отдельно, перейдя по их прямому URL. Используйте HttpResponseRedirect, когда-то подтвержденные обе страницы, обработанные и работающие, как ожидалось.

Благодаря onyeka за помощь в каждом случае.

2

Согласно docs:

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

Итак, в первую очередь, при отображении пустой формы (т. Е не POST), вы будете иметь:

trucks_formset = TrucksFormSet(prefix ='trucksform') 

Кроме того, ваши «данные» не удаются с префиксом, потому что вы Ждете» t изменить имя полей в данных. Префикс переименовывает ваши поля. Вы можете попробовать разместить шаблон в шаблоне, и вы увидите имена скрытых полей.

data = { 
...  'checkbox-TOTAL_FORMS': '2', 
...  'checkbox-INITIAL_FORMS': '0', 
...  'checkbox-MAX_NUM_FORMS': '', 
...  'checkbox-0-overwrite': True, 
...  'checkbox-1-overwrite': False, 
... } 
>>> 
>>> CheckBoxFormSet = formset_factory (CheckBox, extra=1) 
>>> formset = CheckBoxFormSet (data, prefix = 'checkbox') 
+0

Я согласился, и я опубликовал обновление 1 вскоре после моего первоначального сообщения. Префикс работает, но данных нет, и я думаю, что это потому, что Django не имеет набора форм для BooleanField. – dreamzboy

+0

Дополнительно указано в поле «checkbox-TOTAL_FORMS»: «2». Я отредактировал обновление №3, чтобы показать, что это необязательно. – dreamzboy

+0

Hm. Еще раз, мне придется настаивать на том, чтобы вы распечатали свою форму в шаблоне, а не SHELL, чтобы вы могли видеть, что такое данные управления. Вы не публикуете фактические изменения, которые вы делаете в своем сообщении, поэтому трудно сказать, где вы ошибетесь, но определенная проблема с данными управления. – onyeka