2011-12-17 3 views
40

У меня есть приложение, которое использует следующую форму:Django формы с BooleanField всегда недействителен, если не проверено

class ConfirmForm(forms.Form): 
    account_name = forms.CharField(widget=forms.HiddenInput) 
    up_to_date = forms.BooleanField(initial=True) 

я использую форму в следующем шаблоне отрывок:

<form class="confirmform" action="/foo/" enctype="multipart/form-data" method="post"> 
{{ confirm_form.up_to_date }} Check if this data brings the account up to date.<br> 
{{ confirm_form.account_name }} <input type="submit" name="confirm" value="Confirm" /> 
</form> 

Мой взгляд использует следующие Основная структура кода:

if request.method == 'POST': 
    #check for 'confirm' because I actually have multiple forms in this page 
    if 'confirm' in request.POST: 
     confirm_form = ConfirmForm(request.POST) 
     if confirm_form.is_valid(): 
      #do stuff 
     else: 
      c['confirm_form'] = confirm_form 
else: 
    c['confirm_form'] = ConfirmForm({'account_name':'provided_value'}) 

Две ошибки:

1) Даже если у меня есть начальный = True, флажок снят при загрузке страницы

2) Форма всегда недействительна, если я не установить флажок. Он дает ошибки только для up_to_date: «Это поле необходимо».

Я прочитал this similar question, но его решение не относится к моему проекту.

Итак ... что происходит?

Edit:

Я обновил код, чтобы быть более верными своим реальным код.

Проблема №1 была моей ошибкой, потому что я переопределял начальное значение путем привязки данных при создании экземпляра формы.

Проблема №2 Я все еще рассматриваю проблему. Использование required=False на up_to_date устранит проблему, однако не представляется правильным, что с использованием виджета по умолчанию BooleanField может быть либо NULL (вызывает проверку на валидность), либо True, но никогда False.

ответ

32

initial=True должен отображать виджет с checked="checked", поэтому я не вижу проблемы там .. но причина, по которой форма недействительна, заключается в том, что по умолчанию все поля обязательны, если вы не указали иначе.

Field.required¶ По умолчанию, каждый класс поля принимает значение требуется , так что если вы передаете пустое значение - либо None или пустую строки («») - тогда чистой() будет приподнять ValidationError исключение:

Если вы хотите чекбокс или любое другое значение будет необязательным, вам необходимо пройти в required=False в конструктор поля формы.

up_to_date = forms.BooleanField(initial=True, required=False) 
# no longer required.. 
+5

Тем не менее, initial = True не имеет никакого эффекта. Кроме того, почему решение должно сделать поле необязательным? Не может ли BooleanField вернуть false? – dhowland

+0

Выполняет ли HTML-рендеринг с «проверенным»? Вы перезапустили сервер? Можете ли вы запустить отладчик ('import pdb; pdb.set_trace()') в этот момент, чтобы проверить, правильно ли установлен исходный атрибут? 'assert form.fields ['up_to_date']. initial == True' Это сузит нашу проблему. –

+1

Как сделать поле необязательным? 1: документы так говорят. Но 2: флажки - это HTML-элементы, которые не передают данные, будучи «непроверенными». Значение «False» может быть определено только отсутствием ввода. –

0

Убедитесь, что вы не переписываете начальную форму при первой загрузке страницы.

Я изначально не проверял, было ли на самом деле что-либо в запросе.GET. В первый раз, когда страница загружает request.GET - None, а вызов SomeForm (request.GET) фактически уничтожит начальные значения.

def some_view(request): 

    form = SomeForm() 

    if request.method == 'GET': 
     form = SomeForm(request.GET) 

Добавление чека, чтобы убедиться, что в запросе есть что-то. GET исправил это.

def some_view(request): 

    form = SomeForm() 

    if request.method == 'GET' and request.GET: 
     form = SomeForm(request.GET) 
24

В Django формы, булевы поля должны быть созданы с required=False.

Если флажок не установлен, браузеры не отправляют поле в параметрах POST запросов. Не указывая, что поле является необязательным, Django будет рассматривать его как недостающее поле, если не в параметрах POST.

Имхо было бы неплохо для Django, чтобы это поведение по умолчанию для логических полей формы ..

(это уже был дан ответ в комментариях Юджи, но было бы полезно в качестве ответа)

+6

Это пахнет плохим дизайном для меня ... –

8

По в official docs:

Если вы хотите включить логическое значение в вашей форме, которая может быть либо True или False (например, зарегистрированный или незарегистрированный флажок), вы должны помнить, чтобы пройти в required=False при создании BooleanField.

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