2013-05-08 4 views
0

Я хочу написать представление, которое отображает несколько форм, по одному для каждого экземпляра модели, возвращаемого объектным запросом. Таким образом, пользователь может заполнить сразу несколько форм, а затем данные для всех объектов будут сохранены на POST. Вот что у меня есть:Django Multiple Form Submission: одна форма, переписывающая все объекты формы

Вид:

def formView(request, attr): 
    object_list = MyModel.objects.filter(attribute1=attr) 
    if request.method == 'POST': 
      form_list = [MyModelForm(request.POST, instance=x) for x in object_list] 
      if all(form.is_valid for form in form_list): 
       for form in form_list: 
        form.save() 
       return HttpResponseRedirect('/thanks/') 
    else: 
      form_list = [MyModelForm(instance=x) for x in object_list] 
    return render(request, 'formView.html', {'form_list':form_list}) 

HTML:

<table> 
     <thead> 
      <tr> 
       <th>Field1</th> 
       <th>Field2</th> 
       <th>Field3</th> 
      </tr> 
     </thead> 
     <tbody> 
      {% for form in form_list %} 
      <tr> 
       <form method="post">{% csrf_token %} 
       {% for field in form %} 
       <td>{{ field }}</td> 
       {% endfor %} 
       <td><input type="submit" value="Submit" /></td> 
       </form> 
      </tr> 
      {% endfor %} 
     </tbody> 
    </table> 

Поправьте меня, если я ошибаюсь, но вот что я думаю, что мой код в настоящее время делает: когда пользователь заполняет вне формы на странице, а затем нажимает на одну из кнопок Submit, форма, соответствующая этой кнопке Submit, отправляет только мои данные на мое представление, которое затем продолжает сохранять эти данные во всех формах в form_list, тем самым записывая эти же данные в все соответствующие объекты в моей базе данных (что явно не то, что я хочу).

Что бы я хотел, это что-то вроде одной кнопки Submit для всей страницы, так что данные для каждой формы на странице отправляются обратно со связанной формой и сохраняются в соответствующем соответствующем объекте в базе данных. Это возможно?

+0

браузер будет отправлять только форму вашего кнопки отправки связана с и не представит другие. Это просто поведение браузера W3C. Следовательно, каждый '

' имеет свой собственный метод (GET/POST) и URI действия. Вы хотите использовать FormSets, как уже было сказано; обратите внимание, что для рендеринга используется один элемент формы. – gertvdijk

ответ

3

Вы попробовали FormSet, связанный с моделью? Вы можете определить запрос для выбора объектов, которые хотите редактировать, и Django заботится о (почти) всем. https://docs.djangoproject.com/en/dev/topics/forms/modelforms/#changing-the-queryset

Если вы хотите продолжить свой подход (более одной формы на странице, или более одного FormSet на каждой странице), используют prefix атрибут: https://docs.djangoproject.com/en/dev/ref/forms/api/#subclassing-forms и использовать только один тег <form> с одной Submit кнопки.

Пример: http://docs.djangoproject.com/en/dev/topics/forms/formsets/#using-more-than-one-formset-in-a-view

+0

Я попробовал метод FormSet, поскольку мне нравится использовать все части «включенных батарей» Django, но потом понял, что это не сработает, потому что мне нужно исключить одно из полей формы и все же отобразить его значение, t сделать это в цикле '{% for form in formset%}'. Тем не менее, метод 'prefix' работает достаточно хорошо, и +1 для упоминания, что мне тогда нужен только один тег' 'и одна кнопка« Отправить ». – GChorn

+0

Я начал работать с формами только недавно, поэтому я не уверен, что понял, что вы имеете в виду, когда говорите, что не можете исключить одно из полей формы. Вы пытались использовать третий метод, объясненный здесь? https://docs.djangoproject.com/ru/dev/topics/forms/modelforms/#using-the-formset-in-the-template В чем проблема? –

+0

Исключение поля формы не является проблемой, проблема возникает в моем шаблоне, когда я просматриваю формы с помощью '{% for form in formset%}'. Если я исключаю поле при определении моего набора форм, он не будет отображаться ни в одной из форм внутри этого цикла в моем шаблоне.Но я все же хочу отображать данные для исключенного поля, и у меня нет доступа к этим данным в моем наборе форм. Поэтому, используя метод 'префикс', вместо того, чтобы просто отправить« form_list »из моего примера кода в мой шаблон, я создаю список кортежей« значение, форма », а затем я могу перебирать оба одновременно в шаблоне. – GChorn

1

Попробуйте использовать prefix в форме, таким образом, что каждая форма определяется отдельно. x.id будет лучше для префикса.

Что-то вроде:

def formView(request, attr): 
    object_list = MyModel.objects.filter(attribute1=attr) 
    if request.method == 'POST': 
      form_list = [MyModelForm(request.POST, instance=x, prefix=str(x.id)) for x in object_list] 
      if all(form.is_valid for form in form_list): 
       for form in form_list: 
        form.save() 
       return HttpResponseRedirect('/thanks/') 
    else: 
      form_list = [MyModelForm(instance=x, prefix=str(x.id)) for x in object_list] 
    return render(request, 'formView.html', {'form_list':form_list}) 
+0

Спасибо за ответ! Это похоже на самый быстрый способ добиться того, что я ищу, поскольку для моего кода требуется минимальное изменение. Однако теперь, когда пользователь нажимает кнопку «Отправить» на одной из форм, остальные формы пустуют и запускают все «field.errors» для этих форм. Почему это происходит? – GChorn

+0

@GChorn, проверьте, что вы получаете данные всех форм в 'request.POST'. – Rohan

+0

Я понял проблему от чтения другого ответа - с помощью этого метода мне нужно использовать один тег '' только с одной кнопкой «Отправить», а затем просто перебрать мой 'form_list' внутри этого элемента' '. – GChorn