Instalando o Admin – Interface de Administração Automática
A interface de administração automática do Django, vulgo admin, trata-se de uma poderosa interface, simples e rápida de implementar, que possibilita criar, editar, atualizar e deletar registros no banco de dados. É possível criar um sistema funcional em poucas horas usando com seu uso, podendo personalizar a aparência alterarando os templates.
Para instalar o admin, devemos primeiramente adiciona-lo ao INSTALLED_APPS e descomentar 3 linhas no arquivo urls.py.
Arquivo settings.py:
1 2 3 4 5 6 7 8 | INSTALLED_APPS = ( 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.sites', 'sigep.cliente', 'django.contrib.admin', ) |
Arquivo urls.py:
1 2 3 4 5 6 | from django.conf.urls.defaults import * from django.contrib import admin admin.autodiscover() urlpatterns = patterns('', (r'^admin/(.*)', admin.site.root), ) |
O admin possui várias opções de configuração de modo a personalizar o que é exibido. Vamos usar apenas algumas dessas opções para definir a ordem de exibição dos dados, um filtro e um campo de busca.
Crie um arquivo chamado admin.py dentro do diretório da aplicação contendo:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | from django.contrib import admin from sigep.cliente.models import * class ClienteAdmin(admin.ModelAdmin): date_hierarchy = 'data_cadastro' ordering = ['nome'] list_filter = ('id','nome') search_fields = ('nome','cpf') admin.site.register(Cliente,ClienteAdmin) class GrupoVencimentoAdmin(admin.ModelAdmin): pass admin.site.register(GrupoVencimento,GrupoVencimentoAdmin) class BairroAdmin(admin.ModelAdmin): pass admin.site.register(Bairro,BairroAdmin) class LogradouroAdmin(admin.ModelAdmin): pass admin.site.register(Logradouro,LogradouroAdmin) |
Executaremos novamente o syncdb para aplicar as mudanças:
gu@notebook:~/projetos/sigep$ ./manage.py syncdb
Se os passos anteriores foram seguidos corretamente, podemos “brincar” com nossa aplicação agora. Execute o ./manage.py runserver e tente acessar pelo navegador o site http://localhost:8000/admin/ e então será exibida a tela de login.
Para alterar o template do admin, basta copiar o diretório /usr/lib/python2.5/site-packages/django/contrib/admin/templates/admin para dentro do diretório de templates definido no arquivo settings.py, e alterar o código HTML do mesmo.
Criando os Formulários
Deixaremos o admin de lado pois nossa intenção é criar uma aplicação do zero, onde utilizaremos a interface de administração apenas para operações simples, como cadastrar dados de teste. Assim, faz-se necessário criar os formulários da nossa aplicação onde podemos personaliza-los de maneira mais fácil.
Django provê uma poderosa biblioteca chamada ModelForm para manipulação de formulários. São gerados a partir dos modelos criados no arquivo models.py e são renderizados nos templates. Talvez a maior vantagem do ModelForm seja a facilidade no tratamento de erros e validação dos dados submetidos.
Crie um arquivo chamado forms.py dentro do diretório da aplicação, com o seguinte conteúdo:
1 2 3 4 5 6 7 | from sigep.cliente.models import * from django.forms import * class ClienteForm(ModelForm): data_nascimento = DateField(widget=DateTimeInput(format='%d/%m/%Y')) class Meta: model = Cliente |
Assim, automaticamente é criado um formulário contendo todos os campos da tabela cliente. Também é possível inserir algumas propriedades dentro de cada elemento do formulário, como por exemplo style e onblur, utilizando um recurso chamado widgets.
Exemplo usando widgets:
1 2 3 4 5 6 7 | wid_nome = TextInput(attrs={'onBlur': mark_safe("alert('Exemplo widget')")}) wid_cpf = TextInput(attrs={'style':"width:135px;",}) class ClienteForm(ModelForm): nome = CharField(max_length=200,widget=wid_nome) cpf = CharField(widget=wid_cpf) class Meta: model = Cliente |
Mais informações sobre widgets e API do ModelForm estão disponíveis na documentação oficial.
Templates e arquivos estáticos
Templates são as páginas HTML que podem ser renderizadas por algum método controlador. Podem ser considerados arquivos estáticos as imagens, arquivos javascript, arquivos css e qualquer outro arquivo externo ao django.
O sistema de templates do Django permite o uso de tags como if e for em conjunto com o HTML. Não será explicado o uso de tal tags nesse momento.
É possível também usar herança, ou seja, um template filho pode conter os atributos do template pai. Esse conceito ficará mais claro quando criarmos nossos templates.
A princípio serão 3 templates – a página inicial (base.html), a página onde serão exibidos os nomes dos clientes cadastrados (clientes.html) e o formulário para cadastrar clientes (clienteform.html).
Primeiro, vamos criar os diretórios dos arquivos estáticos e dos templates dentro do diretório do projeto. Os nomes devem ser iguais aos que foram definidos nas variáveis MEDIA_ROOT e TEMPLATES_DIR no arquivo settings.py:
gu@notebook:~/projetos/sigep$ mkdir files
gu@notebook:~/projetos/sigep$ mkdir templates
Arquivos Estáticos
Como nossa aplicação ainda está em desenvolvimento não vamos nos preocupar com o visual, logo, não mexeremos com CSS e tão pouco imagens. Mas o importante agora é o Javascript. Utilizaremos uma biblioteca javascript chamada JQuery, que possui muitos recursos e torna bem mais fácil a manipulação de elementos e o uso do ajax.
Vamos ao passo-a-passo:
-
1. Baixem a JQuery no site www.jquery.com e coloquem dentro do diretório files que criamos ainda a pouco.
2. Criaremos o arquivo sigep.js dentro do diretório files. Esse arquivo terá todas as nossas funções em Javascript.
Graças à JQuery podemos nos referir à um elemento HTML com pouco código. Ao invés de usar o document.getElementsById() usamos $('#id_do_elemento').
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | function Editar(urlprocess,objForm,objSelect) { var id = $('#'+objSelect+' option:selected').val(); if ((id > 0) && (id != '')) { $('#'+objForm).attr('action',urlprocess); $('#'+objForm).submit(); } else alert('Selecione um item primeiro.'); } function Excluir(urlprocess,objForm,objSelect) { if (confirm('Tem certeza?')) Editar(urlprocess,objForm,objSelect) } |
3. Vamos fazer um mapeamento de URL apontando para o diretório files.
Edite o arquivo urls.py e adicione no urlpatterns:
1 | (r'^files/(.*)','django.views.static.serve',{'document_root':'/home/gu/projetos/sigep/files'}), |
Agora utilize um editor HTML e vamos para criar nossos templates.
Arquivos de Templates
1. base.html
Esse arquivo será o esqueleto do nosso template. É muito importante que a JQuery seja o primeiro javascript a ser chamado. Basta incluí-lo para poder usar todos os seus recursos.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <meta http-equiv="content-type" content="text/html;charset=utf-8" /> <title>SIGEP - Sistema de Gestão de Provedor</title> <script language="javascript" type="text/javascript" src="/files/jquery-1.2.6.min.js"></script> <script language="javascript" type="text/javascript" src="/files/sigep.js"></script> <style type="text/css"> ul, li { list-style: none; padding: 0px; margin: 0px; } </style> </head> <body> <div id="divMenuSuper"> <a href="/cliente/list/">Pagina Principal</a> </div> <div id="divEsqueleto"> {% block principal %} {% endblock %} </div> </body> </html> |
2. clientes.html
Nesse arquivo serão listados todos os clientes cadastrados. Reparem que não foi definido um action para o form pois será utilizado javascript para submeter o formulário via post.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | {% extends 'base.html' %} {% block principal %} {% ifequal operacao "Cadastrar" %} <form name="buscacliente" id="frmBuscaCliente" method="post" action="/cliente/search/"> <div id="divBuscaCliente"> <br />Buscar por nome ou CPF: <input type="text" name="busca" id="id_busca"> <input type="submit" name="btBuscar" value="Buscar"> </div> </form> <form name="listacliente" id="frmListaCliente" method="post" action=""> <div id="divListaCliente"> <h2>{{titulo|default:"CLIENTES CADASTRADOS"}} - TOTAL: {{clientes|length}}</h2> {% if not clientes %} Nenhum cliente cadastrado. {% else %} Nome: <select name="listaclientes" id="id_cliente"> {% for c in clientes %} <option value="{{c.id}}">{{c.nome|upper}}</option> {% endfor %} </select> <br /><br /> <input type="button" name="btEditar" value="Editar" onclick="Editar('/cliente/edit/','frmListaCliente','id_cliente')"> <input type="button" name="btExcluir" value="Excluir" onclick="Excluir('/cliente/delete/','frmListaCliente','id_cliente')"> {% endif %} </div> </form> {% endifequal %} {% block clienteform %}{% endblock %} {% endblock %} |
3. clienteform.html
Contém nosso formulário para cadastrar e editar dados do cliente. A variável form é um objeto do tipo ClienteForm. É possível gerar todos os campos utilizando {{form.as_table}} ou {{form.as_p}}, porém os campos seriam exibidos dentro de uma tabela ou em parágrafos.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | {% extends 'clientes.html' %} {% block clienteform %} <form name="clienteform" id="frmCliente" method="post" action="{{form_url|default:"/cliente/add/"}}"> <div id="divFormCliente"> <h2>{{operacao|upper|default:"CADASTRAR"}} CLIENTE</h2> <!-- ID do cliente --> <input type="hidden" name="id" id="id_cliente" value="{{id_cliente}}"> Nome ou Razão Social: {{form.nome}}<br /> Apelido ou Nome Fantasia: {{form.apelido}}<br /> CPF ou CNPJ: {{form.cpf}}<br /> RG ou Insc. Estadual: {{form.rg}}<br /> Orgão Exp. RG: {{form.orgao_rg}}<br /> Tipo Pessoa: {{form.tipo_pessoa}}<br /> Data de Nasc.: {{form.data_nascimento}}<br /> Grupo: {{form.grupovencimento}}<br /> Bairro: <select name="bairro"> {% for b in bairros %} <option value="{{b.id}}">{{b.bairro}}</option> {% endfor %} </select><br /> Endereco: <select name="logradouro" id="id_logradouro"></select> Numero: {{form.numero}} CEP: {{form.cep}}<br /> Referencia: {{form.referencia}}<br /><br /> <input type="submit" value="{{operacao|default:"Cadastrar"}}"> </div> </form> <div id="divErro" style="color:red;"> <br /> {% ifequal mensagem "ok" %} Cadastro realizado com sucesso. {% else %} {% for campo in form %} {% if campo.errors %} <br />{{campo.label}} {{campo.errors}} {% endif %} {% endfor %} {% endifequal %} </div> {% endblock %} |
Reparem que criamos manualmente um elemento para representar o endereço (logradouro). Fizemos isso porque esse campo será preenchido utilizando ajax quando for selecionado um bairro.
O formulário será submetido e os campos validados. Então a variável mensagem receberá o valor “ok” se o formulário passar na validação ou “erro” se não passar, e então varre o vetor form obtendo o objeto chamado campo e verifica se há alguma mensagem de erro referente ao campo. Uma melhor abordagem sobre ModelForm pode ser obtida na documentação do Django.
Agora que já criamos nossos templates, podemos começar a escrever nossas views.














Posted in
Tags: 
Muito legal o tuto, parabéns!!
Hugs!!
Muito bom, dei só uma olhada mas com esse tipo de material o Django ira crescer cada vez mais.
Fala rapaz parabens ai ficou muito bom ,,
uma abraço
Gustavo,
Meus sinceros parabéns pelo material, está excelente.
Um desafio:
– O que tu achas de fazer uma versão desse ajax com a biblioteca mootools ?
Parabéns Gustavo,
Ouvi falar da eficiência do Django a poucos dias e procurei algo simples que pudesse me comprovar isso…
Vc sintetizou nesse post tudo o que eu estava procurando! Agora é só me aprofundar no framework. Se existirem mais posts como esse por aí tenho certeza que a comunidade Python e Django vão crescer muito em quantidade e principalmente em qualidade! 100% produção…
Verifiquei que no arquivo forms.py ao usarmos o método mark_safe, devemos incluir a classe safestring do Django.
Para resolver o problema devemos incluir a linha from django.utils.safestring import mark_safe no início do arquivo /cliente/forms.py para importar o método mark_safe.
Abs…
na linha
$(“#”+objHtmlReturn).append(”+item.fields[fieldreturn]+”);
qd escolho o bairro da um erro dizendo q a palavra ou o campo “fieldreturn” nao está definido por isso nao carrega as ruas no outro select
Excelente tutorial, colega.
Parabéns XD
Opa, tudo bom.
Primeiro quero parabenizá-lo pelo artigo. Segundo informo que o método javascript declarado acima para atualizar o select html está quebrado. Criei outro método jQuery, que ficou assim:
$( function() {
$(“select#id_bairro”).change(
function() {
$.getJSON( “/cliente/getlogradouros?id=” + $(this).val(),
function(j) {
var options = ‘———- ‘;
for ( var i = 0; i < j.length; i++) {
options += ”
+ j[i].fields['logradouro']
+ ”;
}
$(“#id_logradouro”).html(options);
$(“#id_logradouro option:first”).attr(’selected’,
’selected’);
$(“#id_logradouro”).attr(‘disabled’, false);
})
$(“#id_logradouro”).attr(’selected’, ’selected’);
})
})
Para que ele funcione, o metodo no módulo views.py precisa ser mudado para o método GET, que no meu caso ficou assim:
def getlogradouros( request ):
id = int( request.GET.get( ‘id’ ) )
lista = Logradouro.objects.filter( bairro = id )
if lista.count() > 0:
json = serializers.serialize( “json”, lista )
else:
lista = [{"pk":"0", "fields":{'logradouro':"Nenhum registro"}}]
json = simplejson.dumps( lista )
return HttpResponse( json, mimetype = “application/json” )
Ola gostei do material que vc publicou, vc terminou a segunda parte deste tutorial referente ao sistema???
@Luiz, nao cheguei a terminar, mas escrevi um artigo aqui no blog que fala um pouco sobre. O titulo é “Servidor Linux com Proxy e Controle de Banda”.
[]’s