Django com MySQL, JQuery, Ajax e JSON – Parte 1

Criando as Views

Antes de começarmos a falar sobre as views, vamos configurar o arquivo urls.py e mapear nossas URLs. Não detalharemos esse processo muito menos sobre expressões regulares utilizadas.
Vamos mapear todos as nossas views de uma vez, alterando novamente a variável urlpatterns dentro do arquivo urls.py:

1
2
3
4
5
6
7
8
9
urlpatterns = patterns('',
    (r'^admin/(.*)', admin.site.root),
    (r'^cliente/list/$','sigep.cliente.views.list'),
    (r'^cliente/add/$','sigep.cliente.views.add'),
    (r'^cliente/delete/$','sigep.cliente.views.delete'),
    (r'^cliente/edit/$','sigep.cliente.views.edit'),
    (r'^cliente/update/$','sigep.cliente.views.update'),
    (r'^cliente/search/$','sigep.cliente.views.search'),
)

Agora sim, vamos ao que interessa…
No Django as views são os controllers do modelo MVC, ou seja, métodos que intermediam a comunicação entre os modelos (banco de dados) e os templates (HTML).
Vamos escrever nossos métodos no arquivo views.py localizado dentro do diretório da aplicação cliente:

Método 1: list
Descrição: Exibe os clientes cadastrados e um formulário para cadastrar novo cliente. Na realidade o template exibido é o clienteform que por sua vez extende o template clientes.html, resultando na exibição dos 2 ao mesmo tempo.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# -*- coding: utf-8 -*-
from sigep.cliente.models import *
from sigep.cliente.forms import *
from django.shortcuts import render_to_response
 
def list(request):
  clienteform = ClienteForm()
  clientes = Cliente.objects.all()
  bairros = Bairro.objects.all()
 
  return render_to_response('clienteform.html',{
    'form':clienteform,
    'clientes':clientes,
    'bairros':bairros,
    'operacao':'Cadastrar',
  })

Explicando o código:
Definimos a codificação do arquivo como UTF8
Criamos um objeto do tipo ClienteForm, que foi definido no arquivo forms.py
A variável clientes obtem todos os clientes cadastrados
A variável bairros obtem todos os bairros cadastrados
O metodo listar retorna o arquivo de template a ser renderizado com o valor das variáveis passadas como argumentos.

Método 2: add
Descrição: Cadastra os dados do cliente no banco de dados.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from django.http import HttpResponse
def add(request):
  if request.method == 'POST':
    clienteform = ClienteForm(request.POST)
    if clienteform.is_valid():
      clienteform.save()
      mensagem = 'Cadastro realizado com sucesso.'
    else:
      mensagem = 'Erro na validacao do form.'
 
    clientes = Cliente.objects.all()
    operacao = 'Cadastrar'
    return render_to_response('clienteform.html',{'form':clienteform, 'clientes':clientes, 'mensagem':mensagem, 'operacao':operacao})
  else:
    return HttpResponse("Nao foi submetido nenhum formulario.")

Notem o quanto a validação de um formulário é ridiculamente simples no Django. É criado um objeto do tipo ClienteForm, passando como parâmetro o formulário submetido e chamando o método is_valid().
Uma novidade nesse código foi o uso do método HttpResponse que apenas exibe um texto na tela do navegador.

Método 3: delete
Descrição: Remove o cliente do banco de dados a partir do id fornecido.

1
2
3
4
5
6
7
8
9
10
11
def delete(request):
  if request.method == 'POST':
    id = request.POST.get('listaclientes')
    if id > 0:
      Cliente.objects.get(pk=id).delete()
      return HttpResponseRedirect('/cliente/list/')
 
    else:
      return HttpResponse("Nenhum cliente foi selecionado. Id=0.")
  else:
    return HttpResponse("Nao foi submetido nenhum formulario.")

Em

1
Cliente.objects.get(pk=id)

, estamos selecionando na tabela cliente o registro cuja chave primária (pk) seja igual ao valor da variável id. Essa variável poderia ter outro nome, e não necessáriamente o nome do campo da tabela que também é id.

Método 4: edit
Descrição: Obtém os dados do cliente a partir do id fornecido e preenche o formulário usado no cadastro.

1
2
3
4
5
6
7
8
9
10
11
12
13
def edit(request):
  if request.method == 'POST':
    id = request.POST.get('listaclientes')
    if id > 0:
      clientes = Cliente.objects.get(pk=id)
      clienteform = ClienteForm(instance=clientes)
      form_url = '/cliente/update/'
      operacao = 'Atualizar'
      return render_to_response('clientes.html' {'form':clienteform, 'id_cliente':id, 'form_url':form_url, 'operacao':operacao})
    else:
      return HttpResponse("Nenhum cliente foi selecionado. id=0.")
  else:
    return HttpResponse("Nao foi submetido nenhum formulario.")

Método 5: update
Descrição: Atualiza os dados do cliente e tenta fazer a validação do mesmo jeito que o método add.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
def update(request):
  if request.method == 'POST':
    id = request.POST.get('id')
    if id > 0:
      cliente = Cliente.objects.get(pk=id)
      clienteform = ClienteForm(request.POST,instance=cliente)
      if clienteform.is_valid():
        clienteform.save()
        return HttpResponseRedirect('/cliente/list/')
      else:
        mensagem = 'erro'
        operacao = 'Atualizar'
        return render_to_response('clienteform.html',{'form':clienteform, 'mensagem':mensagem, 'id_cliente':id, 'operacao':operacao})
 
    else:
      return HttpResponse("Nenhum cliente foi selecionado. id=0.")
  else:
    return HttpResponse("Nao foi submetido nenhum formulario.")

Método 6: search
Descrição: A partir da palavra-chave fornecida, é feita uma busca case-insensitive na tabela cliente nos campos nome e cpf. Equivalente em SQL à WHERE nome LIKE “%palavra%” OR cpf LIKE “%palavra%”. Para tal tarefa vamos utilizar o objeto Q, pertecente à biblioteca django.db.models.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
def search(request):
  if request.method == 'POST':
    palavra = request.POST.get('busca')
    if len(palavra) > 0:
      from django.db.models import Q
      clientes = Cliente.objects.filter(Q(nome__icontains=palavra) | Q(cpf__icontains=palavra))
      bairros = Bairro.objects.all()
      clienteform = ClienteForm()
      return render_to_response('clienteform.html',{
        'form':clienteform,
        'clientes':clientes,
        'bairros':bairros,
        'operacao':'Cadastrar',
        'titulo':'RESULTADO DA BUSCA'
      })
    else:
      return HttpResponse("Nao foi digitado nada no campo de busca.")
  else:
      return HttpResponse("O formulario nao foi submetido.")

Terminamos de criar nossas views, entretanto nosso sistema não possui a mínima segurança. Vamos criar então nossa interface de autenticação de usuários.

Autenticação de Usuários

Nosso método de autenticação será o mesmo utilizado pelo admin. Criaremos apenas a interface de login, um template simples, e todo o processo de autenticação e validação será feito pelo Django.
Na primeira vez em que foi executado o script manage.py syncdb, o Django perguntou se você queria criar uma conta de super-usuário. Essa é a mesma conta usada pelo admin. Se por acaso você não criou essa conta, execute o comando abaixo para criar um novo:
gu@notebook:~/projetos/sigep$ ./manage.py createsuperuser

Vamos criar nosso template de login, dentro do diretório de templates, com o nome loginform.html:

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
<!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>
  <title>SIGEP - Login</title>
  <meta http-equiv="content-type" content="text/html;charset=utf-8" />
  <script language="Javascript" type="text/javascript">
  function Validar(objForm)
  {
    if (objForm.username.value != "" && objForm.password.value != "")
      return true;
      else {
        alert("Preencha corretamente todos os campos.");
        objForm.username.focus();
        return false;
      }
    }
  </script>
</head>
 
<body>
<center>
<form action="." name="login" id="frmLogin" method="post" onsubmit="return Validar(this)">
<div id="divLogin" align="left">
  <br />Usuario: {{form.username}}
  <br />Senha: {{form.password}}
  <input type="hidden" name="next" value="{{ next }}" />
  <br /><br />
  <input type="submit" name="btOk" value="Ok" />
</div>
</form>
 
{% if form.errors %}
<div align="center" style="padding-top:50px;font-size:16px;color:red;">
  Erro: Usuario ou senha incorretos.
</div>
{% endif %}
 
</center>
</body>
</html>

Nosso template é um arquivo HTML simples, com uma função Javascript que verifica se os campos usuario e senha foram preenchidos e então envia o formulário. No action foi inserido um ponto (.) porque o método que vai renderizar esse template automaticamente substituirá pelo action verdadeiro.

E então vamos fazer o mapeamento de URL para o processo de login. No arquivo urls.py, adicione na variável urlpatterns o seguinte:

1
2
r'^auth/login/$','django.contrib.auth.views.login', {'template_name': '/home/gu/projetos/sigep/templates/loginform.html'}),
(r'^auth/logout/$','django.contrib.auth.views.logout_then_login'),

Observem que não estamos fazendo um mapeamento para nenhuma das views que criamos, pois o Django provê métodos próprios para esse tipo de autenticação. Definimos apenas o template que criamos anteriormente para ser usado.
Existem 3 variáveis que não vêm definidas por padrão e que são necessárias para a autenticação funcionar. Vamos defini-las então no arquivo settings.py:

1
2
3
LOGIN_URL = '/auth/login/'
LOGOUT_URL = '/auth/logout'
LOGIN_REDIRECT_URL = '/cliente/list/'

LOGIN_URL e LOGOUT_URL devem ter o mesmo valor que foi utilizado no mapeamento de URL logo acima. LOGIN_REDIRECT_URL é a view a ser chamada quando o login for efetuado.

Para finalizar essa parte, precisamos definir quais das nossas views só poderão ser acessadas se o usuário estiver logado. Para isso vamos utilizar o método login_required() presente na biblioteca django.contrib.auth.decorators.
No arquivo views.py, devemos importar o método login_required. Para cada view que seja necessário o login efetuado, devemos declarar uma variavel com o mesmo nome da view, recebendo o valor de login_required passando como argumento a view. Ex.:

1
2
3
4
from django.contrib.auth.decorators import login_required
def welcome(request):
  return HttpResponse('Bem-vindo! Voce esta logado no sistema.')
welcome = login_required(welcome)

Conforme o exemplo acima, vamos usar o login_required() abaixo de cada view que escrevemos.

1
2
3
4
5
6
7
def list(request):
  ...
list = login_required(list)
 
def add(request):
 ...
add = login_required(add)

Nossa aplicação está quase completa. Está faltando o uso do ajax para exibir as ruas cadastradas a partir do bairro selecionado.

Pages: 1 2 3 4 5

You can leave a response, or trackback from your own site.

11 Responses to “Django com MySQL, JQuery, Ajax e JSON – Parte 1”

  1. Relsi disse:

    Muito legal o tuto, parabéns!!

    Hugs!!

  2. Abaster disse:

    Muito bom, dei só uma olhada mas com esse tipo de material o Django ira crescer cada vez mais.

  3. Rânielli The head disse:

    Fala rapaz parabens ai ficou muito bom ,,
    uma abraço

  4. Leandro disse:

    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 ?

  5. 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…

  6. 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…

  7. Maria disse:

    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

  8. Excelente tutorial, colega. :)

    Parabéns XD

  9. Helder disse:

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

  10. luiz Martins disse:

    Ola gostei do material que vc publicou, vc terminou a segunda parte deste tutorial referente ao sistema???

    • gustavohenrique disse:

      @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

Leave a Reply

Powered by WordPress | Shop the Best Verizon Wireless Deals. | Thanks to Best CD Rates, Credit Cards and Credit card