Как использовать значения формы из несвязанной формы
Вопрос
У меня есть веб-отчет, который использует форму Django (новые формы) для полей, которые управляют запросом, используемым для создания отчета (дата начала, дата окончания, ...).Проблема, с которой я сталкиваюсь, заключается в том, что страница должна работать с использованием начальных значений формы (несвязанных), но я не могу получить доступ к полю cleaned_data, если не вызову is_valid().Но is_valid() всегда терпит неудачу в несвязанных формах.
Похоже, что формы Django были разработаны с учетом варианта использования редактирования данных таким образом, что несвязанная форма на самом деле не полезна ни для чего, кроме отображения HTML.
Например, если у меня есть:
if request.method == 'GET':
form = MyForm()
else:
form = MyForm(request.method.POST)
if form.is_valid():
do_query(form.cleaned_data['start_date'], form.cleaned_data['end_date'])
is_valid() завершится неудачей, если это GET (поскольку оно несвязано), и если я сделаю:
if request.method == 'GET':
form = MyForm()
do_query(form.cleaned_data['start_date'], form.cleaned_data['end_date'])
else:
form = MyForm(request.method.POST)
if form.is_valid():
do_query(form.cleaned_data['start_date'], form.cleaned_data['end_date'])
первый вызов do_query вызывает исключения для form.cleaned_data, которое не является допустимым полем, поскольку is_valid() не был вызван.Похоже, я должен сделать что-то вроде:
if request.method == 'GET':
form = MyForm()
do_query(form['start_date'].field.initial, form['end_date'].field.initial)
else:
form = MyForm(request.method.POST)
if form.is_valid():
do_query(form.cleaned_data['start_date'], form.cleaned_data['end_date'])
то есть, не существует общего интерфейса для получения значений формы между связанной формой и несвязанной.
Кто-нибудь видит более чистый способ сделать это?
Решение
Если вы добавите этот метод в свой класс form:
def get_cleaned_or_initial(self, fieldname):
if hasattr(self, 'cleaned_data'):
return self.cleaned_data.get(fieldname)
else:
return self[fieldname].field.initial
затем вы могли бы переписать свой код следующим образом:
if request.method == 'GET':
form = MyForm()
else:
form = MyForm(request.method.POST)
form.is_valid()
do_query(form.get_cleaned_or_initial('start_date'), form.get_cleaned_or_initial('end_date'))
Другие советы
Несвязанный означает, что с формой не связаны данные (ни начальные, ни предоставленные позже), поэтому проверка может завершиться неудачей.Как упоминалось в других ответах (и в вашем собственном заключении), вы должны предоставить начальные значения и проверить наличие как привязанных данных, так и начальных значений.
Примером использования форм является обработка форм и проверка, поэтому у вас должны быть некоторые данные для проверки, прежде чем вы получите доступ cleaned_data
.
Вы можете передать словарь начальных значений в свою форму:
if request.method == "GET":
# calculate my_start_date and my_end_date here...
form = MyForm( { 'start_date': my_start_date, 'end_date': my_end_date} )
...
Смотрите на официальная документация по API формуляров, где они это демонстрируют.
Редактировать:Основываясь на ответах других пользователей, возможно, это самое чистое решение:
if request.method == "GET":
form = MyForm()
form['start_date'] = form['start_date'].field.initial
form['end_date'] = form['end_date'].field.initial
else:
form = MyForm(request.method.POST)
if form.is_valid():
do_query(form.cleaned_data['start_date'], form.cleaned_data['end_date'])
Хотя я этого еще не пробовал;кто-нибудь может подтвердить, что это работает?Я думаю, что это лучше, чем создание нового метода, потому что этот подход не требует, чтобы другой код (возможно, написанный не вами) знал о вашем новом "волшебном" средстве доступа.