Django Form Preview - Como trabalhar com 'cleaned_data'

votos
3

Graças a Insin para responder a uma anterior pergunta relacionada a esta.

Sua resposta funcionou e funciona bem, no entanto, estou perplexo com o fornecimento de 'cleaned_data', ou mais precisamente, como usá-lo?

class RegistrationFormPreview(FormPreview):
    preview_template    = 'workshops/workshop_register_preview.html'
    form_template       = 'workshops/workshop_register_form.html'

    def done(self, request, cleaned_data):
        # Do something with the cleaned_data, then redirect
        # to a success page. 

        registration            = Registration(cleaned_data)
        registration.user       = request.user
        registration.save()
        # an attempt to work with cleaned_data throws the error: TypeError 
        # int() argument must be a string or a number, not 'dict'
        # obviously the fk are python objects(?) and not fk_id
        # but how to proceed here in an easy way?



        # the following works fine, however, it seems to be double handling the POST data
        # which had already been processed in the django.formtools.preview.post_post
        # method, and passed through to this 'done' method, which is designed to 
        # be overidden.
        '''
        form                    = self.form(request.POST)   # instansiate the form with POST data
        registration            = form.save(commit=False)   # save before adding the user
        registration.user       = request.user              # add the user
        registration.save()                                 # and save.
        '''

        return HttpResponseRedirect('/register/success')

Para referência rápida, aqui está o conteúdo do método post_post:

def post_post(self, request):
    Validates the POST data. If valid, calls done(). Else, redisplays form.
    f = self.form(request.POST, auto_id=AUTO_ID)
    if f.is_valid():
        if self.security_hash(request, f) != request.POST.get(self.unused_name('hash')):
            return self.failed_hash(request) # Security hash failed.
        return self.done(request, f.cleaned_data)
    else:
        return render_to_response(self.form_template,
            {'form': f, 'stage_field': self.unused_name('stage'), 'state': self.state},
            context_instance=RequestContext(request))
Publicado 09/03/2009 em 22:39
fonte usuário
Em outras línguas...                            


1 respostas

votos
9

Eu nunca tentei o que você está fazendo aqui com um ModelForm antes, mas você pode ser capaz de usar o operador ** para expandir seu dicionário cleaned_data para a palavra-chave argumentos esperados para o seu construtor de Registro:

   registration = Registration (**cleaned_data)

O construtor para suas classes do modelo ter argumentos de palavra-chave que a classe meta Modelo de Django converte em nível instância atributos no objeto resultante. O operador ** é uma convenção de chamada que diz ao Python para expandir seu dicionário para esses argumentos nomeados.

Em outras palavras...

O que você está fazendo atualmente equivale a isto:

registration = Registration ({'key':'value', ...})

O que não é o que você quer porque o construtor espera argumentos nomeados em oposição a um dicionário que contém os argumentos de palavra-chave.

O que você quer fazer é esta

registration = Registration (key='value', ...)

Que é análogo a este:

registration = Registration (**{'key':'value', ...})

Mais uma vez, eu nunca tentei, mas parece que ele iria trabalhar, desde que você não está fazendo nada extravagante com seu formulário, como adicionar novos atributos a ele que não são esperadas por seu construtor do registro. Nesse caso, você iria provavelmente ter de modificar os itens no dicionário cleaned_data antes de fazer isso.

Realmente, parece que você está perdendo alguma da funcionalidade inerente ModelForms passando pelo utilitário de forma prévia, no entanto. Talvez você deve levar seu caso de uso para a lista de discussão Django e ver se há uma melhoria potencial para esta API que poderia fazê-lo funcionar melhor com ModelForms.

Editar

Aquém do que eu descrevi acima, você pode simplesmente extrair os campos de seu dicionário cleaned_data "à mão" e passar aqueles em seu construtor de Registro também, mas com a ressalva de que você tem que lembrar de atualizar esse código como você adicionar novos campos ao seu modelo.

registration = Registration (
    x=cleaned_data['x'],
    y=cleaned_data['y'],
    z=cleaned_data['z'],
    ...
)
Respondeu 10/03/2009 em 00:46
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more