Pergunta

Tenho um relatório web que utiliza um formulário Django (novos formulários) para campos que controlam a consulta utilizada para gerar o relatório (data de início, data de término,...).O problema que estou tendo é que a página deve funcionar usando os valores iniciais do formulário (não vinculados), mas não consigo acessar o campo clean_data a menos que eu chame is_valid().Mas is_valid() sempre falha em formulários não vinculados.

Parece que os formulários do Django foram projetados com o caso de edição de dados, de modo que um formulário não vinculado não seja realmente útil para outra coisa senão a exibição de HTML.

Por exemplo, se eu tiver:

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() falhará se for um GET (já que não está vinculado) e se eu fizer isso:

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'])

a primeira chamada para do_query aciona exceções em form.cleaned_data, que não é um campo válido porque is_valid() não foi chamado.Parece que tenho que fazer algo como:

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'])

isto é, não existe uma interface comum para recuperar os valores do formulário entre um formulário vinculado e um não vinculado.

Alguém vê uma maneira mais limpa de fazer isso?

Foi útil?

Solução

Se você adicionar este método à sua classe de formulário:

def get_cleaned_or_initial(self, fieldname):
        if hasattr(self, 'cleaned_data'):
            return self.cleaned_data.get(fieldname)
        else:
            return self[fieldname].field.initial

você poderia então reescrever seu código como:

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'))

Outras dicas

Não consolidado significa que não há dados associados ao formulário (iniciais ou fornecidos posteriormente), portanto a validação pode falhar.Conforme mencionado em outras respostas (e em sua própria conclusão), você deve fornecer valores iniciais e verificar os dados vinculados e os valores iniciais.

O caso de uso para formulários é o processamento de formulários e validação, então você deve ter alguns dados para validar antes de acessar cleaned_data.

Você pode passar um dicionário de valores iniciais para o seu formulário:

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} )
...

Veja o documentação oficial da API de formulários, onde eles demonstram isso.

editar:Com base nas respostas de outros usuários, talvez esta seja a solução mais limpa:

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'])

Eu ainda não tentei isso;alguém pode confirmar que isso funciona?Acho que isso é melhor do que criar um novo método, porque essa abordagem não requer outro código (possivelmente não escrito por você) para saber sobre seu novo acessador 'mágico'.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top