Back-End

Publicidade

O Django traz embutido um poderoso recurso para criação de formulários e validação dos dados nele inseridos, de forma rápida, fácil e intuitiva. Esta ferramenta é a mesma utilizada na administração automática.

Para exemplificar, criaremos um novo projeto teste com uma app contato. Abra o terminal e digite:

django-admin.py startproject teste
cd teste/
python manage.py startapp contato

Edite o arquivo settings.py, incluindo a app contato no INSTALLED_APPS:

settings.py

(...)
INSTALLED_APPS = (
    'contato',
)

No diretório contato, recém criado pelo Django, crie um arquivo em branco e salve sob o nome forms.py.

Digite nele o seguinte código:

forms.py

# -*- coding:utf-8 -*-
from django import forms
from django.contrib.localflavor.br.br_states import STATE_CHOICES
   
class FormContato(forms.Form):
    nome = forms.CharField()
    email = forms.EmailField(label=u'E-mail')
    cidade = forms.CharField()
    estado = forms.ChoiceField(choices=STATE_CHOICES)
    mensagem = forms.CharField(widget=forms.Textarea())

Comentando linha-a-linha:

# -*- coding:utf-8 -*-

– Define o arquivo com a codificação UTF-8, permitindo o uso de acentos. Lembre-se de alterar o encoding do arquivo também para UTF-8.

from django import forms

– Importa a biblioteca forms do Django, com as classes e métodos necessários para criação de formulários.

from django.contrib.localflavor.br.br_states import STATE_CHOICES

– Importa do ‘localfalvor.br’ a lista de estados brasileiros a serem incluídos no formulário.

class FormContato(forms.Form)

– Define a classe herdada do forms.Form. Nesta classe definiremos os campos do formulário.

nome = forms.CharField()

email = forms.EmailField(label=u’E-mail’)

cidade = forms.CharField()

estado = forms.ChoiceField(choices=STATE_CHOICES)

mensagem = forms.CharField(widget=forms.Textarea())

– Os atributos da classe FormContato serão os campos do formulário a ser gerado. Estrutura semelhante a dos models. Os atributos poderão ser do tipo:

  • BooleanField
  • CharField
  • ChoiceField
  • TypedChoiceField
  • DateField
  • DateTimeField
  • DecimalField
  • EmailField
  • FileField
  • FilePathField
  • FloatField
  • ImageField
  • IntegerField
  • IPAddressField
  • MultipleChoiceField
  • NullBooleanField
  • RegexField
  • TimeField
  • URLField

Veja a referência completa em: http://docs.djangoproject.com/en/dev/ref/forms/fields/

Pela definição do atributo, o Django automaticamente validará os dados. Do localflavor.br podemos importar mais campos específicos para o Brasil como CPF, CEP e telefone. É possível também criar seu próprio campo para o formulário ou o definir por expressão regular com o RegexField. Mais abaixo criaremos outras validações.

No arquivo views.py da app ‘contato’, digite:

views.py


# -*- coding:utf-8 -*-
from django.shortcuts import render_to_response
from teste.contato.forms import FormContato

def contato(request):
    if request.method=='POST':
        form = FormContato(request.POST)
        if form.is_valid():
            pass
            # aqui vai o código para enviar o e-mail
            # veja mais em http://docs.djangoproject.com/en/dev/topics/email/
    else:
        form = FormContato()
    return render_to_response('contato.html', {'form': form})

A view contato funciona da seguinte maneira:

  • Se o usuário submeteu o formulário (POST): instancia a classe FormContato com os dados submetidos (request.POST) e verifica se são válidos (form.is_valid())
  • Caso contrário instancia a classe FormContato e envia para o template contato.html (abaixo)

Falta agora o template onde o formulário irá aparecer. Antes disso crie um diretório chamado templates na raiz do projeto (teste/templates), depois abra o arquivo settings.py e defina o caminho deste diretório:

settings.py

(...)
TEMPLATE_DIRS = (
    '/path/para/teste/templates',
)
(...)

O template contato.html, no diretório /templates:

contato.html


<html>
    <head>
        <title>Contato</title>
    </head>

    <body>
        <form action="" method="post" id="form1">
        {{ form.as_ul }}
        <input type="submit" />
        </form>
    </body>
</html>

O método as_ul monta o formulário usando tags <ul> e <li>. Caso prefira utilize as_table para tabelas ou as_p para montar o formulário com parágrafos (<p>).

Por fim, defina a url para acessar a página:

urls.py

from django.conf.urls.defaults import *

urlpatterns = patterns('',
    (r'^fale-conosco/
, 'teste.contato.views.contato'), )

Rode o projeto:

python manage.py runserver

O resultado será algo como:

Preencha o formulário incorretamente e clique em Enviar Dados.

Para a mensagem aparecer em português altere o settings.py, LANGUAGE_CODE = ‘pt-br’.

Para alterar a aparência do formulário utilize CSS. Abaixo, um exemplo real de um formulário criado com o Forms e customizado com CSS.

Validação dos dados submetidos

Às vezes precisamos de mais validações de dados, além das automáticas feitas pelo framework. Por exemplo, verificar se o CPF da pessoa já está cadastrado no banco de dados ou se a confirmação da senha bate com a senha digitada. Em nosso (simples) exemplo vamos disparar um erro caso o nome da pessoa seja ‘Teste’. Para isso, no arquivo forms.py, inclua o seguinte método:

forms.py

# -*- coding:utf-8 -*-
from django import forms
from django.contrib.localflavor.br.br_states import STATE_CHOICES
   
class FormContato(forms.Form):
    nome = forms.CharField()
    email = forms.EmailField(label='E-mail')
    cidade = forms.CharField()
    estado = forms.ChoiceField(choices=STATE_CHOICES)
    mensagem = forms.CharField(widget=forms.Textarea())
   
    def clean_nome(self):
        if self.cleaned_data['nome']=='Teste':
            raise forms.ValidationError(u'Digite um nome melhor.')
        else:
            return self.cleaned_data['nome']

O form.is_valid() sempre executará os métodos com o nome clean_<nome-do-atributo> antes de retornar. Para acessar o valor digitado pelo usuário utilize self.cleaned_data[‘<nome-do-atributo>’].

Os forms podem ser completamente customizados, mesmo o HTML gerado, leia mais em http://docs.djangoproject.com/en/dev/ref/forms/api/#more-granular-output.

Gostou? No próximo artigo veremos os model forms, formulários criados automaticamente a partir de um determinado model.

, 'teste.contato.views.contato'),\n)\n\u003C\u002Fcode\u003E\u003C\u002Fpre\u003E\n\u003C\u002Fdiv\u003E\n\u003Cp\u003ERode o projeto:\u003C\u002Fp\u003E\n\u003Cp\u003E\n\u003Ckbd\u003Epython manage.py runserver\u003C\u002Fkbd\u003E\u003C\u002Fp\u003E\n\u003Cp\u003EO resultado será algo como:\u003C\u002Fp\u003E\n\u003Cp\u003E\n\u003Cimg src=\"http:\u002F\u002Fconteudo.imasters.com.br\u002F10756\u002Fimg1.png\" alt=\"\" \u002F\u003E\u003C\u002Fp\u003E\n\u003Cp\u003EPreencha o formulário incorretamente e clique em \u003Cstrong\u003EEnviar Dados\u003C\u002Fstrong\u003E.\u003C\u002Fp\u003E\n\u003Cp\u003E\n\u003Cimg src=\"http:\u002F\u002Fconteudo.imasters.com.br\u002F10756\u002Fimg2.png\" alt=\"\" \u002F\u003E\u003C\u002Fp\u003E\n\u003Cp\u003EPara a mensagem aparecer em português altere o \u003Cstrong\u003Esettings.py\u003C\u002Fstrong\u003E, \u003Cstrong\u003ELANGUAGE_CODE = ‘pt-br’\u003C\u002Fstrong\u003E.\u003C\u002Fp\u003E\n\u003Cp\u003E\nPara alterar a aparência do formulário utilize CSS. Abaixo, um exemplo real de um formulário criado com o Forms e customizado com CSS.\n\u003C\u002Fp\u003E\n\u003Cp\u003E\u003Cimg src=\"http:\u002F\u002Fconteudo.imasters.com.br\u002F10756\u002Fimg3.png\" alt=\"\" \u002F\u003E\u003C\u002Fp\u003E\n\u003Ch4\u003EValidação dos dados submetidos\u003C\u002Fh4\u003E\n\u003Cp\u003EÀs vezes precisamos de mais validações de dados, além das automáticas feitas pelo framework. Por exemplo, verificar se o CPF da pessoa já está cadastrado no banco de dados ou se a confirmação da senha bate com a senha digitada. Em nosso (simples) exemplo vamos disparar um erro caso o nome da pessoa seja ‘Teste’. Para isso, no arquivo \u003Cstrong\u003Eforms.py\u003C\u002Fstrong\u003E, inclua o seguinte método:\u003C\u002Fp\u003E\n\u003Cp\u003E\u003Cspan class=\"c2\"\u003Eforms.py\u003C\u002Fspan\u003E\u003C\u002Fp\u003E\n\u003Cdiv class=\"codigo\"\u003E\n\u003Cpre\u003E\u003Ccode\u003E# -*- coding:utf-8 -*-\nfrom django import forms\nfrom django.contrib.localflavor.br.br_states import STATE_CHOICES\n \nclass FormContato(forms.Form):\n nome = forms.CharField()\n email = forms.EmailField(label='E-mail')\n cidade = forms.CharField()\n estado = forms.ChoiceField(choices=STATE_CHOICES)\n mensagem = forms.CharField(widget=forms.Textarea())\n \n def clean_nome(self):\n if self.cleaned_data['nome']=='Teste':\n raise forms.ValidationError(u'Digite um nome melhor.')\n else:\n return self.cleaned_data['nome']\u003C\u002Fcode\u003E\u003C\u002Fpre\u003E\n\u003C\u002Fdiv\u003E\n\u003Cp\u003EO \u003Cstrong\u003Eform.is_valid()\u003C\u002Fstrong\u003E sempre executará os métodos com o nome clean_<nome-do-atributo> antes de retornar. Para acessar o valor digitado pelo usuário utilize self.cleaned_data[‘<nome-do-atributo>’].\u003C\u002Fp\u003E\n\u003Cp\u003EOs forms podem ser completamente customizados, mesmo o HTML gerado, leia mais em \u003Ca href=\"http:\u002F\u002Fdocs.djangoproject.com\u002Fen\u002Fdev\u002Fref\u002Fforms\u002Fapi\u002F#more-granular-output\" class=\"ext\"\u003Ehttp:\u002F\u002Fdocs.djangoproject.com\u002Fen\u002Fdev\u002Fref\u002Fforms\u002Fapi\u002F#more-granular-output\u003C\u002Fa\u003E.\u003C\u002Fp\u003E\n\u003Cp\u003EGostou? No próximo artigo veremos os \u003Cstrong\u003Emodel forms\u003C\u002Fstrong\u003E, formulários criados automaticamente a partir de um determinado model.\u003C\u002Fp\u003E\n","excerpt":"","link":"https:\u002F\u002Fimasters.com.br\u002Fback-end\u002Fdjango-forms","date":"24 nov, 2008","thumbnail":"","externalMention":null,"author":{"id":22500,"thumbnail":"https:\u002F\u002Fsecure.gravatar.com\u002Favatar\u002F272143398432ba5a61ba365b9ef3b0eb?s=96&d=mm&r=g","name":"Renato Garcia Pedigoni","description":"é desenvolvedor web desde 2000. Graduando em Informática Biomédica pela USP, tem como principais plataformas .NET, Java e Python. Atua como programador freelancer.","slug":"renato_garcia_pedigoni","url":"https:\u002F\u002Fimasters.com.br\u002Fperfil\u002Frenato_garcia_pedigoni","registered":"2008-11-15 07:57:30","social":{"linkedin":null,"youtube":null,"facebook":"","twitter":"","instagram":null,"github":null,"url":"","mail":"renatopedigoni@gmail.com"},"articles_count":1,"views_count":100,"certifications":null,"conquests":null,"office":null,"articles":[]},"categories":[{"title":"Back-End","slug":"back-end","id":7158,"link":"https:\u002F\u002Fimasters.com.br\u002Fback-end"},{"title":"Desenvolvimento","slug":"desenvolvimento","id":7234,"link":"https:\u002F\u002Fimasters.com.br\u002Fdesenvolvimento"}],"tags":[{"title":"Django","slug":"django","id":7294,"link":"https:\u002F\u002Fimasters.com.br\u002Fdjango"}],"seo":{"open_graph":{"title":"Django Forms - iMasters - We are Developers","description":"","type":"article","locale":"pt_BR","site_name":"iMasters - We are Developers","image":false,"modified_time":"2018-05-23T22:18:25-03:00","published_time":"2008-11-24T10:31:00-03:00"},"twitter":{"title":"Django Forms - iMasters - We are Developers","description":"","type":"summary_large_image","image":false}},"articleSocial":{"facebook":"https:\u002F\u002Fwww.facebook.com\u002Fsharer?u=https:\u002F\u002Fimasters.com.br\u002Fback-end\u002Fdjango-forms","twitter":"https:\u002F\u002Ftwitter.com\u002Fshare?url=https:\u002F\u002Fimasters.com.br\u002Fback-end\u002Fdjango-forms","linkedin":"https:\u002F\u002Fwww.linkedin.com\u002FshareArticle?url=https:\u002F\u002Fimasters.com.br\u002Fback-end\u002Fdjango-forms"},"type":"post","articleViews":100}},"author":{"success":false,"isFetchingPagination":false,"maxPages":0,"page":1,"data":{}},"category":{"success":false,"data":{}},"categoryArticles":{"success":false,"isFetchingPagination":false,"maxPages":0,"page":1,"data":{}},"categoryMostRead":{"success":false,"data":{}},"home":{"success":false,"featured":[],"options":{"homeProducts":[]},"allCategories":{},"featuredArticles":{},"magazines":{"data":[]},"tv":{},"forums":[],"authorsRanking":{},"events":{},"certificatedUsers":[],"news":[]},"page":{"success":false,"data":{}},"magazine":{"success":false,"magazines":[]},"schedule":{"success":false,"data":{}},"searchResult":{"success":false,"totalPosts":0,"totalPage":0,"currentPage":1,"posts":[],"term":"","orderBy":"recents","currentFilter":"articles","isLoading":true,"isLoadingPagination":false},"singleNews":{"success":false,"data":{}},"listNews":{"success":false,"isFetchingPagination":false,"maxPages":0,"page":1,"data":[]},"sponsors":{"success":true,"data":[]},"header":{"success":true,"menus":{"main":[{"ID":138755,"order":1,"parent":0,"title":"Back-End","url":"https:\u002F\u002Fimasters.com.br\u002Fback-end","attr":"package","target":"","classes":"package","xfn":"","description":"Tecnologias utilizadas no backend da aplicação","object_id":7158,"object":"category","type":"taxonomy","type_label":"Categoria","children":[]},{"ID":138756,"order":2,"parent":0,"title":"Mobile","url":"https:\u002F\u002Fimasters.com.br\u002Fmobile","attr":"package","target":"","classes":"package","xfn":"","description":"Conteúdos sobre Desenvolvimento Mobile nas plataformas iOS (iPhone e iPad) e Android.","object_id":4255,"object":"category","type":"taxonomy","type_label":"Categoria","children":[]},{"ID":139476,"order":3,"parent":0,"title":"Front End","url":"https:\u002F\u002Fimasters.com.br\u002Ffront-end","attr":"package","target":"","classes":"package","xfn":"","description":"Conteúdos sobre HTML5, CSS3, Javascript, JQuery, Web Standards e SEO.","object_id":7304,"object":"category","type":"taxonomy","type_label":"Categoria","children":[]},{"ID":138764,"order":4,"parent":0,"title":"DevSecOps","url":"https:\u002F\u002Fimasters.com.br\u002Fdevsecops","attr":"package","target":"","classes":"package","xfn":"","description":"","object_id":1,"object":"category","type":"taxonomy","type_label":"Categoria","children":[]},{"ID":139204,"order":5,"parent":0,"title":"Design & UX","url":"https:\u002F\u002Fimasters.com.br\u002Fdesign-ux","attr":"package","target":"","classes":"package","xfn":"","description":"Conteúdos sobre User Experience, Arquitetura de Informação, Usabilidade, Acessibilidade, Design Responsivo, Teoria do Design e Photoshop.","object_id":7252,"object":"category","type":"taxonomy","type_label":"Categoria","children":[]},{"ID":138759,"order":6,"parent":0,"title":"Data","url":"https:\u002F\u002Fimasters.com.br\u002Fdata","attr":"package","target":"","classes":"package","xfn":"","description":"Conteúdos sobre Banco de Dados Oracle, MySQL, SQL Server, MongoDB, DB2 e Postgre SQL, sobre BI e análise de dados.","object_id":16,"object":"category","type":"taxonomy","type_label":"Categoria","children":[]},{"ID":138758,"order":7,"parent":0,"title":"APIs e Microsserviços","url":"https:\u002F\u002Fimasters.com.br\u002Fapis-microsservicos","attr":"package","target":"","classes":"package","xfn":"","description":"Dicas e tutoriais sobre APIs públicas como Facebook, Twitter, PayPal, Buscapé, Google, etc e arquitetura de microsserviços, com códigos de exemplo, vídeos, cursos.","object_id":4257,"object":"category","type":"taxonomy","type_label":"Categoria","children":[]}],"secondary":[{"ID":138752,"order":1,"parent":0,"title":"Fórum iMasters","url":"https:\u002F\u002Fforum.imasters.com.br\u002F","attr":"","target":"_blank","classes":"","xfn":"","description":"","object_id":138752,"object":"custom","type":"custom","type_label":"Link personalizado","children":[]},{"ID":139067,"order":2,"parent":0,"title":"Portal E-Commerce Brasil","url":"http:\u002F\u002Fwww.ecommercebrasil.com.br","attr":"","target":"","classes":"","xfn":"","description":"","object_id":139067,"object":"custom","type":"custom","type_label":"Link personalizado","children":[]},{"ID":156289,"order":3,"parent":0,"title":"iMasters Business","url":"http:\u002F\u002Fbusiness.imasters.com.br","attr":"","target":"","classes":"","xfn":"","description":"","object_id":156289,"object":"custom","type":"custom","type_label":"Link personalizado","children":[]}]}},"webinar":{"success":false,"data":{}},"webinars":{"success":false,"isFetchingPagination":false,"maxPages":0,"page":1,"data":{"next":[],"prev":[]}},"tv":{"sectionNameLeft":{"small":"Vídeos","large":"iMasters TV"},"itemsLeft":[{"text":"Em Destaque","slug":"recents"},{"text":"Mais Vistos","slug":"most-viewed"}],"sectionNameRight":{"small":"","large":""},"itemsRight":[{"text":"Mais Recentes","slug":"recents"},{"text":"7Masters","slug":"7-masters"},{"text":"PHP Experience","slug":"php-experience"},{"text":"Android DevConference","slug":"android-devconference"},{"text":"Busca","slug":"search"}],"currentVideo":"recents","currentListVideo":"recents"}} window.__SERVER_VARS__ = {"applicationRestUrl":"https:\u002F\u002Fadmin.imasters.com.br\u002Fwp-json","applicationBaseUrl":"https:\u002F\u002Fadmin.imasters.com.br"} , 'teste.contato.views.contato'), )

Rode o projeto:

python manage.py runserver

O resultado será algo como:

Preencha o formulário incorretamente e clique em Enviar Dados.

Para a mensagem aparecer em português altere o settings.py, LANGUAGE_CODE = ‘pt-br’.

Para alterar a aparência do formulário utilize CSS. Abaixo, um exemplo real de um formulário criado com o Forms e customizado com CSS.

Validação dos dados submetidos

Às vezes precisamos de mais validações de dados, além das automáticas feitas pelo framework. Por exemplo, verificar se o CPF da pessoa já está cadastrado no banco de dados ou se a confirmação da senha bate com a senha digitada. Em nosso (simples) exemplo vamos disparar um erro caso o nome da pessoa seja ‘Teste’. Para isso, no arquivo forms.py, inclua o seguinte método:

forms.py

# -*- coding:utf-8 -*-
from django import forms
from django.contrib.localflavor.br.br_states import STATE_CHOICES
   
class FormContato(forms.Form):
    nome = forms.CharField()
    email = forms.EmailField(label='E-mail')
    cidade = forms.CharField()
    estado = forms.ChoiceField(choices=STATE_CHOICES)
    mensagem = forms.CharField(widget=forms.Textarea())
   
    def clean_nome(self):
        if self.cleaned_data['nome']=='Teste':
            raise forms.ValidationError(u'Digite um nome melhor.')
        else:
            return self.cleaned_data['nome']

O form.is_valid() sempre executará os métodos com o nome clean_<nome-do-atributo> antes de retornar. Para acessar o valor digitado pelo usuário utilize self.cleaned_data[‘<nome-do-atributo>’].

Os forms podem ser completamente customizados, mesmo o HTML gerado, leia mais em http://docs.djangoproject.com/en/dev/ref/forms/api/#more-granular-output.

Gostou? No próximo artigo veremos os model forms, formulários criados automaticamente a partir de um determinado model.

De 0 a 10, o quanto você recomendaria este artigo para um amigo?

Renato Garcia Pedigoni

edit1 Artigo(s)

é desenvolvedor web desde 2000. Graduando em Informática Biomédica pela USP, tem como principais plataformas .NET, Java e Python. Atua como programador freelancer.