2015-12-16 2 views
0

При размещении 2 форм в представлении с использованием формы | хрустящий фильтр и этот ответ обрабатывать 2 формы в одном виде: Proper way to handle multiple forms on one page in Django Я получаю ошибку this.Несколько Django Crispy Forms In One View

views.py:

def test_form(request): 
    if not request.user.is_authenticated(): 
     return redirect(settings.LOGIN_URL) 
    title = 'test form' 
    row_control_form = RowControlForm(request.POST or None) 
    entry_form = EntryForm(request.POST or None) 

    context = { 
     'title': title, 
     'row_control_form': row_control_form, 
     'entry_form': entry_form, 
    } 

    if 'row_control_submit' in request.POST: 
     if row_control_form.is_valid(): 
      row_control_form.save() 

     if 'entry_submit' in request.POST: 
      if entry_form.is_valid(): 
       entry_form.save() 

    return render(request, "timesheet/test_form.html", context) 

forms.py

class RowControlForm(forms.ModelForm): 
    class Meta: 
     model = RowControl 
     fields = ['month_control_record', 'department', 'activity', 'notes'] 

    def clean(self): 
     cleaned_data = self.cleaned_data 
     # Ensures row is unique 
     try: 
      RowControl.objects.get(month_control_record=cleaned_data['month_control_record'], 
            department=cleaned_data['department'], 
            activity=cleaned_data['activity'], 
            notes=cleaned_data['notes']) 

     except RowControl.DoesNotExist: 
      pass 

     else: 
      raise ValidationError('This row already exists') 

     # Always return cleaned data 
     return cleaned_data 


class EntryForm(forms.ModelForm): 
    class Meta: 
     model = Entry 
     fields = ['row_control', 'date', 'hours'] 

    def clean(self): 
     cleaned_data = self.cleaned_data 

     # Ensures data is unique (only 1 hours entry for each date and row_control) 
     try: 
      Entry.objects.get(row_control=cleaned_data['row_control'], 
           date=cleaned_data['date']) 

     except Entry.DoesNotExist: 
      pass 

     else: 
      raise ValidationError('This entry already exists') 

     # Always return cleaned data 
     return cleaned_data 

test_form.html

{% extends "base.html" %} 
{% load crispy_forms_tags %} 


{% block content %} 
<div class="col-md-6 col-md-offset-3"> 
    <h1 class="page-header"> Form Test </h1> 
    <form method="POST" action="{{ request.path }}"> 
    {% csrf_token %} 
    {{ row_control_form|crispy }} 

    <button class="btn btn-primary" type="submit" value="Submit" name="row_control_submit" ><i class="fa fa-lg fa-floppy-o"></i> Save</button> </form> 
    </br> 
</div> 

<div class="col-md-6 col-md-offset-3"> 
    <h1 class="page-header"> Form Test </h1> 
    <form method="POST" action="{{ request.path }}"> 
    {% csrf_token %} 
    {{ entry_form|crispy }} 

    <button class="btn btn-primary" type="submit" value="Submit" name="entry_submit" ><i class="fa fa-lg fa-floppy-o"></i> Save</button> </form> 
    </br> 
</div> 

{% endblock %} 

Чтобы обеспечить контекст ошибка: Линия 42 из forms.py является:

Entry.objects.get(row_control=cleaned_data['row_control'], 

EDIT: Дальнейшее исследование показало, что проблема в том, что обе формы валидация выполняются в настоящее время не имеет значения, который подают кнопка нажата, request.POST при подаче достоверные данные для RowControlForm является:

<QueryDict: {'csrfmiddlewaretoken': ['HffmmbI31Oe0tItYDfYC4MoULQHL0KvF'], 'notes': ['Cool'], 'row_control_submit': ['Submit'], 'month_control_record': ['1'], 'department': ['1'], 'activity': ['1']}> 

Поэтому entry_submit не в request.POST и что проверка не должна еще работать это?

ответ

1

Во-первых, вам нужно решить эту линию clean метода вашей формы

def clean(self): 
    ... 
    Entry.objects.get(row_control=cleaned_data['row_control'], 

Вы не можете предположить, что row_control будет в cleaned_data. Вам либо нужно добавить чек if 'row_control' in cleaned_data, либо поймать KeyError, а затем обновить остальную часть метода соответствующим образом. Вы должны исправить это, даже если вы не видели эту ошибку, пока не поместите несколько форм на одну страницу. Невозможно вызвать ошибку сервера 500, оставив значение из запроса POST. Пользователи могут это сделать, даже если на странице есть только одна форма.

Проверка выполняется для обеих форм, поскольку вы создаете экземпляры обеих форм с данными сообщения, независимо от того, какая кнопка отправки была нажата.

row_control_form = RowControlForm(request.POST or None) 
entry_form = EntryForm(request.POST or None) 

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

И, наконец, рекомендуется перенаправить пользователя после того, как они успешно отправили действительную форму.

+0

Я заметил это и планирую исправить его, однако я убедился, что row_control находится в request.POST при отправке и когда на представлении есть только одна форма, она отлично работает. – ijames55

+0

Добавьте некоторые сведения о печати/протоколировании, чтобы выяснить, что происходит: добавьте 'print self.errors' и' print 'row_control' в cleaned_data' в метод 'clean()' и добавьте 'print request.POST' к вашему Посмотреть. – Alasdair

+0

self.errors пуст. Кроме того, row_control пуст, поскольку row_control является частью EntryForm, и его проверка еще выполняется при отправке RowControlForm ... – ijames55

Смежные вопросы