Back-End

10 jun, 2013

Fazendo integração entre Django e GoogleMaps

Publicidade

Após um longo tempo sem escrever, volto a falar sobre a melhor plataforma de desenvolvimento que já trabalhei, e neste artigo falarei sobre a integração entre o Django e o GoogleMaps. Mesmo existindo apps para quase tudo no Django, decidi mostrar como fazer tal integração sem utilizar algo pronto, pois poderemos ver que mesmo quando necessitamos criar algo que ainda não exista na comunidade Django o trabalho também é simples, prático e rápido.

Os passos que iremos seguir são:

  1. Criar um model com campos para latitude e longitude
  2. Criar a chave para uso da API do GoogleMaps
  3. Criar os arquivos JavaScript necessários para identificarmos a localização do nosso visitante
  4. Subscrever o save_model do nosso model para tratar os valores do item 3
  5. Subscrever o template do admin do nosso model para registrar a posição do usuário e também para mostrar o mapa

Estaremos também utilizando o HTML5 e a funcionalidade de georeferenciamento, nativa da linguagem que é compatível com os principais navegadores do mercado. Se você ainda pensa que o HTML5 é o futuro, mude rápido o seu conceito, pois o uso dele já é obrigatório caso queira desenvolver um software/site de qualidade.

Vamos agora ao que interessa que é fazer o projeto – lembrando que irei utilizar o admin do Django mesmo, assim fica até melhor de entender.

1 – Criar um model com campos para latitude e longitude

Aqui não temos muito o que falar, pois é bem simples criar um model e mais ainda criar dois atributos para receber os dados de latitude e longitude; no caso, esses atributos são do tipo CharField.

2 – Criar a chave para uso da API do GoogleMaps

  1. Logar na sua conta do Google
  2. Acessar o site http://goo.gl/uc8nL
  3. Seguir os passos para configuração da conta

3 – Criar os arquivos JavaScript necessários para funcionamento

Aqui teremos um pouco de trabalho. O primeiro arquivo JavaScript a ser desenvolvido configurado na verdade é apenas para identificar se o navegador do cliente tem suporte à tecnologia de geolocalização do HTML5, e para novamente não termos muito trabalho, vamos utilizar o Modernizr, que é um arquivo JavaScript que nos permite, entre outras coisas, testarmos se determinada funcionalidade do HTML5 é compatível com o navegador do usuário do nosso sistema. Basta para tanto baixar o arquivo e configurar no seu projeto.
Depois de configurado no projeto, vamos fazer o teste para identificarmos a funcionalidade de georeferenciamento no navegador do cliente. O código é este aqui:

if (Modernizr.geolocation) {
    navigator.geolocation.getCurrentPosition(function(posicao){
            $("#demanda_form").append("<input type='hidden' name='codigo_longitude' id='codigo_longitude' value="+ posicao.coords.longitude +">");
            $("#demanda_form").append("<input type='hidden' name='codigo_latitude' id='codigo_latitude' value="+ posicao.coords.latitude +">");
            $("#id_longitude").val(posicao.coords.longitude);
            $("#id_latitude").val(posicao.coords.latitude);
        });
}

Nas linhas 3  e 4, adiciono via JavaScript dois campos do tipo hidden no formulário do nosso model; no caso, chamado de demanda.

4 – Subscrever o save_model do nosso model para tratar os valores do item 3

Os dois campos da linha 3 e 4 serão resgatados no save_model para podermos vinculá-los aos campos latitude e longitude do nosso model. Vamos fazer isso agora, para tanto devemos ter o admin.py configurado para nosso model; no meu caso, minha configuração do save_model ficou assim:

def save_model(self, request, obj, form, change):
    try:
        requisitante = Requisitante.objects.get(id_user=request.user.pk)
        obj.solicitante = requisitante
        obj.chave_anonimo = requisitante.chave_identificacao
        obj.longitude = request.POST.get('codigo_longitude') or None
        obj.lagitude = request.POST.get('codigo_latitude') or None
        obj.save()
    except:
        pass

Nesse caso, as linhas que interessam para o exemplo são as de número 6 e 7, e os comandos request.POST.get(‘codigo_longitude’) e request.POST.get(‘codigo_lagitude’). Esses dois comandos fazem justamente o “resgate” dos valores que inserimos no JavaScript e os vincula aos campos do nosso model longitude e latitude- o resto do bloco já deve ser conhecido por vocês, estou apenas subscrevendo o save. Outra configuração que precisamos fazer no nosso admin é criar um método retornar um botão na grid (tabela), permitindo assim que o usuário exiba o mapa. A configuração ficou assim:

def popup_georeferenciamento(self, obj):
    try:
        if obj.latitude and obj.longitude:
            return '<a href="#" class="btn btn-large" id="btn_georeferenciamento_%s_%s"> <i class="icon-screenshot"></i> Mapa</a>' % (obj.latitude, obj.longitude)
        else:
            return ''
    except:
        pass

O botão criado no código acima e inserido como um item no list_display do nosso admin pode ser visto na imagem abaixo, com o label de Mapa.

5 – Subscrever o template do admin do nosso model para registrar a posição do usuário e também para mostrar o mapa

Essa pode ser a parte mais “complicada”, pois temos que ter um certo entendimento do funcionamento dos templates do admin, mas vou tentar explicar da melhor forma possível. A mágica do Django em criar a interface Front-end dos apps e dos models é tarefa da app admin, que configuramos no nosso settings com o ’django.contrib.admin’. Feito isso, devemos também configurar o TEMPLATE_DIR = (). Aqui podemos determinar ao Django que os arquivos HTML (Templates) do admin estão no diretório X; no meu caso, eu sempre crio um diretório chamado ‘templates’ dentro da estrutura do meu projeto e copio os arquivos padrões do admin para esse diretório. Para mim, é necessária essa configuração, pois eu não utilizo a estrutura padrão de HTML e CSS do Django. Eu tenho templates customizados para utilizar o BootStrap do Twitter, isso também possibilita customizar o template do nosso model ‘demanda’. Não que essa seja a única possibilidade para poder inserir nele um elemento com o objetivo de mostrar o mapa quando o usuário clicar num determinado botão; basta para isso que criemos uma estrutura como esta: meuprojeto-> templates -> admin -> minhaaplicacao -> nomedotemplatequequerosubscrever; no meu caso, estou subscrevendo o change_list.html. A imagem final fica assim, na qual o mapa aparecerá antes do grid contendo os itens:

Captura-de-Tela-46

Esse é o resultado final da nossa configuração. Para atingir tal estrutura, foram adicionadas as estrutura abaixo no change_list.html da nossa app.

<div id="maps_google">
  <div id="mapa"></div>
  <a href="#" id="btn_fechar_mapa_demanda" class="btn">Fechar</a>
</div>

Veja que, como falei, é tudo bem simples e direto. Veremos agora o que considero o único arquivo da nossa estrutura que pode causar alguma dúvida, é um JavaScript (jQuery), utilizado para mostrar a DIV na qual o mapa será inserido e posicionar a caixa da legenda.

$("a[id^='btn_georeferenciamento_']").live("click", function(){
        var infowindow = new google.maps.InfoWindow();
        var botao = $(this).attr('id').split('_');
        var latitude = botao[2];
        var longitude = botao[3];
        var opcoes = {
            center: new google.maps.LatLng(longitude, latitude),
            // position: new google.maps.LatLng(longitude, latitude),
            zoom: 15,
            mapTypeId: google.maps.MapTypeId.ROADMAP,
            content: 'Origem da demanda.'
        }
        $("#maps_google").css("display", "block");
        $("#maps_google").slideDown('slow');
        $("#mapa").css("display", "block");
        $("#mapa").slideDown('slow');
        var local = new google.maps.LatLng(longitude, latitude);
        var mapa = new google.maps.Map(document.getElementById("mapa"), opcoes);
        mapa.setCenter(local);
        infowindow.setPosition(local);
        infowindow.open(mapa);
        infowindow.setContent('Origem da demanda.');
    });

Na linha 1, é disparada uma função quando houver o click no botão criado no item 4, é uma função jQuery simples; na linha 2, criamos a variável infowindow, já utilizando a API do GoogleMaps; na linha 3, é resgatado o valor do atributo ID do botão, onde temos armazenado os valores da latitude e longitude que são transferidas para as variáveis latitude e longitude; na linha 6, é feito o uso de uma variável que chamei de opções, onde são configurados parâmetros conforme a documentação da API do GoogleMaps. Os parâmetros podem ser estudados na documentação, da linha 13 à 16 faço a exibição das divs onde irei inserir o mapa, já na linha 17 crio uma outra variável que contém a localização conforme o resultado da função LatLng do GoogleMaps. Depois, na linha 18, faço a inserção do mapa na div “mapa”, com o comando google.maps.Map(document.getElementById(“mapa”), opcoes); perceba aqui o uso da variável criada na linha 6 opcoes, que nada mais é que o dicionário com os valores para configuração do mapa.

Bom, espero ter sido bem claro, e que este artigo sirva como base para que vocês possam ampliar o conhecimento e uso do GoogleMaps, afinal o que vemos agora são cada vez mais aplicações que fazem uso do georeferenciamento ou geolocalização.