2009-03-09 6 views
3

Merci à Insin pour avoir répondu à un précédent question associé à celui-ci. Sa réponse a fonctionné et fonctionne bien, cependant, je suis perplexe quant à la fourniture de «données_souties», ou plus précisément, comment l'utiliser?Django Form Preview - Comment utiliser 'clean_data'

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

Pour une référence rapide, voici le contenu de la méthode 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)) 
+0

@Antonius Vous devriez jeter un oeil au guide de style Python: http://www.python.org/dev/peps/pep-0008/ – orokusaki

Répondre

9

Je ne l'ai jamais essayé ce que vous faites ici avec un ModelForm avant, mais vous pourriez être en mesure d'utiliser la ** opérateur pour élargir votre dictionnaire cleaned_data dans les arguments de mots-clés attendus pour votre constructeur d'enregistrement:

registration = Registration (**cleaned_data) 

Le constructeur à vos classes de modèle prennent des arguments clés qui Dja La méta-classe Model de ngo est convertie en attributs au niveau de l'instance sur l'objet résultant. L'opérateur ** est une convention d'appel qui indique à Python d'étendre votre dictionnaire à ces arguments.

En d'autres termes ...

Ce que vous faites est actuellement équivalent à ceci:

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

Ce qui est pas ce que vous voulez parce que le constructeur attend des arguments mot-clé, par opposition à un dictionnaire contient vos arguments de mot-clé.

Qu'est-ce que vous voulez faire est ce

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

Ce qui est analogue à ceci:

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

Encore une fois, je ne l'ai jamais essayé, mais il semble que cela fonctionnerait aussi longtemps comme vous ne faites rien de fantaisie avec votre formulaire, comme l'ajout de nouveaux attributs qui ne sont pas attendus par votre constructeur d'enregistrement. Dans ce cas, vous devrez probablement modifier les éléments du dictionnaire clean_data avant de procéder. Il semble que vous perdiez certaines des fonctionnalités inhérentes à ModelForms en passant par l'utilitaire d'aperçu de formulaire. Peut-être devriez-vous apporter votre cas d'utilisation à la liste de diffusion de Django et voir s'il y a une amélioration potentielle à cette API qui pourrait le faire fonctionner mieux avec ModelForms.

Modifier

court de ce que je viens de décrire ci-dessus, vous pouvez toujours extraire les champs de votre dictionnaire cleaned_data « à la main » et de passer trop ceux dans votre constructeur d'enregistrement, mais avec la mise en garde que vous N'oubliez pas de mettre à jour ce code lorsque vous ajoutez de nouveaux champs à votre modèle.

registration = Registration (
    x=cleaned_data['x'], 
    y=cleaned_data['y'], 
    z=cleaned_data['z'], 
    ... 
) 
+0

gee, il est si facile quand vous obtenez une bonne aide! bien fait et merci ... Je me demandais à quoi ces ** étaient destinés! (C'était le seul mod nécessaire, en ajoutant le **) –

+0

Si tout ce que vous essayez de faire est de créer un modèle basé sur les données de formulaire (à quoi il ressemble), pourquoi ne pas simplement utiliser un ModelForm et être fait? –

+0

@Carl Pour clarifier, il * utilise * un ModelForm, mais l'utilisation intermédiaire de FormPreview vous empêche d'utiliser certaines fonctionnalités de ModelForm (construction d'objet et commit) sans traitement redondant. C'est pourquoi j'ai suggéré de prendre son cas d'utilisation sur la liste de diffusion Django. –

Questions connexes