El blog de Trespams

[ x ]

Faig servir les cookies de Google Analytics per al control de visites i estadístiques..
És una pardalada, però la llei diu que us he d'avisar, ja veus. Així que si visitau aquest blog donau-vos per informats o sortiu ara mateix i netejau les cookies del vostre navegador. Si continuau llegint, suposaré que ja us està bé. Si vols saber com llevar les cookies del teu navegador: aquí ho pots trobar

Django class based views (III)

En aquest apunt veurem com fer servir les generic class views per a fer feina amb formularis.

Seguirem la documentació de Django que tracta dels formularis. Allà ens fa referència a un formulari de contacte creat com:

from django import forms

class ContactForm(forms.Form):
    subject = forms.CharField(max_length=100)
    message = forms.CharField()
    sender = forms.EmailField()
    cc_myself = forms.BooleanField(required=False)

i la vista associada

def contact(request):
    if request.method == 'POST': # If the form has been submitted...
        form = ContactForm(request.POST) # A form bound to the POST data
        if form.is_valid(): # All validation rules pass
            # Process the data in form.cleaned_data
            # ...
            return HttpResponseRedirect('/thanks/') # Redirect after POST
    else:
        form = ContactForm() # An unbound form

    return render_to_response('contact.html', {
        'form': form,
    })

El que farem ara és fer el mateix però fent servir les generic class views.

El primer que hem de veure és què hem de fer servir. Necessitam gestionar un formulari, la seva validació i tornar la redirecció cap a una nova plana web en cas que tot vagi bé.

Si feim una ullada a la jerarquia de classes del mòdul edit podem veure que la classes que compleix tot el que volem es diu FormView.

FormView està composada pel mixin TemplateResponseMixin que ja coneixem i BaseFormView que a la seva vegada està format per dos mixins més FormMixin i ProcessFormView.

FormMixin ens proporciona els mètodes per a gestionar el form i ProcessFormView que descendeix de View ens proporciona les respostes a les cridades get, post i put.

L'equivalent fent servir les generic class views ens queda:

class ContactView(FormView):
    form_class=ContactForm
    success_url = reverse_lazy('main_thanks')
    template_name = 'main/index.html'

    def form_valid(self, form):
        # process data
        print form.cleaned_data
        return super(ContactView, self).form_valid(form)

és a dir, hem de dir li a la classe quin formulari farem servir, això ho feim a form_class o bé amb la rescriptura del mètode get_form_class que ens ha proporcionat el mixin FormMixin o fin i tot instanciant el formulari directament si fem la rescriptura de get_form

Els mètodes form_valid i form_invalid ens permeten definir què em de fer amb el formulari. Normalment ens bastarà sobreescriure el mètode form_valid per a adaptar-lo a les nostres necessitats.

I qui crida al mètode is_valid del formulari? Doncs el post que prové de ProcessFormView. Recordem que un mixin té accés a tot l'objecte que el fa servir, i per tant també té accés als mètodes el mixin FormMixin.

Suposem ara que volem que el nostre formulari agafi uns certs valors inicials, això ho podem fer amb l'atribut initial definit a FormMixin o bé a partir de la reescriptura del mètode get_initial, segons la nostra aplicació ens convindrà un mètode o un altre.

class ContactView(FormView):
    form_class=ContactForm
    success_url = reverse_lazy('main_thanks')
    template_name = 'main/index.html'
    initial = {'subject': u'This is a test form'}

    def form_valid(self, form):
        # process data
        print form.cleaned_data
        return super(ContactView, self).form_valid(form)

Si a més hem de passar dades addicionals a la plantilla Django, FormMixin ens proporciona un altre vell conegut, el mètode get_context_data que fa el mateix que feia al TemplateView. Això sí, ara hem de tenir cura de cridar al mètode pare, ja que als kwargs hi ha la definició del formulari. Per a evitar-nos conèixer què fa i que no fa, millor cridar al mètode pare i a partir d'aquí afegir-hi les variables que necessitem:

class ContactView(FormView):
    form_class=ContactForm
    success_url = reverse_lazy('main_thanks')
    template_name = 'main/index.html'
    initial = {'subject': u'This is a test form'}

    def form_valid(self, form):
        # process data
        print form.cleaned_data
        return super(ContactView, self).form_valid(form)

    def get_context_data(self, **kwargs):
        context = super(ContactView, self).get_context_data(**kwargs)
        context['msg'] = u'Hello World'
        return context

I no hem de perdre de vista que estam fent feina amb classes. Podem anar afegint els mètodes que necessitem a la classe, de manera que cada funció ens quedi manejable.

I ja per acabar un petit avís, he fet servir reverse_lazy per a obtenir el valor de la url, però aquesta funció no hi és a Django 1.3. Per utilitzar el nom de la url enlloc de la url en sí, en Django 1.3 o bé hem de sobreescriure get_success_url o bé utilitzar l'snippet que apareix a Django Snippets i que resol això d'una manera molt elegant:

from django.utils.functional import lazy
from django.core.urlresolvers import reverse
reverse_lazy = lambda name=None, *args : lazy(reverse, str)(name, args=args)

Això encara dóna per més, fins al proper article!

blog comments powered by Disqus
<<<<<<< main/templates/puput/base.html ======= >>>>>>> main/templates/puput/base.html