Skip to content

mfagundes/djang-leaflet-test

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

20 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Criando um sistema Geo super simples com Django

Por super simples, entende-se:

  • Um sistema sem a necessidadde da instalação e configuração de uma base de dados PostgreSQL/GIS;
  • Um sistema clásico tipo Create, Update, Delete (CRUD) para dados geográficos;
  • Um sistema que não demande operações e consultas espaciais;

Visão geral de proposta:

Vamos criar um ambiente virtual python e instalar a framework django, para criar o sistema, assim como alguns módulos como jsonfield, que nos vai habilitar a criação de campos json em nossa base de dados, assim como django-geojson. Este ultimo, que depende do jsonfield cria uma instância de dados geográficos, baseando-se e json. Por isso o nome geojson. O uso desses dois módulos nos permitirá o desenvolvimento de um sistema de gestão de dados geográficos sem a necessidade de termos instalado um sistema de gerenciamento de dados geográficos, como o PostGIS. Sim, nosso sistema será bem limitado a algumas tarefas. Mas en contrapartida, poderemos desenvolvê-lo e implementar soluções "corriqueiras" de forma facilitada.

Nosso projeto se chamará de mapProj. E nele vou criar uma app, chamada core. Essa organização e nomenclartura usada, vem das sugestões do Henrique Bastos. Afinal, o sistema está nascendo. Ainda que eu tenha uma ideia do que ele será, é interessante iniciar com uma app "genérica" e a partir do momento que o sistema se torne complexo, poderemos desacoplá-lo em diferentes apps.

Criando ambiente de desenvolvimento, projeto e nossa app:

python -m venv .djleaflet # cria ambiente virtual python
# uma vez ativado o ambiente virtual:
pip install --upgrade pip
pip install django jsonfield django-geojson
django-admin startproject mapProj . # criando projeto
cd mapProj
manage startapp core # criando app dentro do projeto
manage migrate # criando a base de dados incial
manage createsuperuser # criando superusuário

Adicionando os módulos e a app ao projeto

Agora é adicionar ao settings.py, a app criada e os módulos que usaremos.

# setting.py
INSTALLED_APPS = [
    ...
    'mapProj.core',
    'djgeojson',
]

Perceba que para pode acessar as classes de alto nível criadas pelo pacote djgeojson, teremos que adicioná-lo ao INSTALLED_APPS do settings.py.

Criando a base de dados

Ainda que eu concorde com o Henrique Bastos, de que a visão de começar os projetos django pelo models.py é um tanto "perigosa", por colocar ênfase em uma parte da app e, em muitos casos, negligenciar vários outros atributos e ferramentas que o django nos oferece, irei negligenciar sua abordagem. Afinal, estamos criando um sistema para a gestão de dados geográficos... dados geográficos. Enfim, o objetivo deste artigo não é explorar todo o potencial do django, mas sim apresentar uma solução simples no desenvolvimento e implementação de um sistema de gestão de dados geográficos, vou seguir assim, mesmo.

Em models.py usaremos instâncias de alto nivel que o django nos brinda para criar e configurar os campos e as tabelas que teremos em nosso sistema, bem como alguns comportamentos do sistema, como o processo de sanitização dos dados.

Vejam que antes de tudo, eu importo de djgeojson a classe PointField. O que o django-geojson fez foi criar uma classe [com estrutura de dados goegráfico] de alto nível que no banco será armazenado em um campo json:

All geometry types are supported and respectively validated : GeometryField, PointField, MultiPointField, LineStringField, MultiLineStringField, PolygonField, MultiPolygonField, GeometryCollectionField.

Ao fazer isso, poderemos trabalhar com esse dado como se fosse um dado geográfico, com métodos e sistemas de validação desse campo. Contudo, nem tudo são flores: Consultas e operações espaciais não são contemplados. Para tais casos, vocÇe precisará do PstGIS. Mais informações sobre o djgeojson

Como estou fazendo um sistema multipropósito, vou tentar manter bem genérico. A ideia é que vocês possam imaginar o que adequar para um sistema especialista na sua área de interesse. Vou criar, então, uma tabela para mapear "fenómenos" (quaisquer). Eses terão os campos "nome", "data", "hora" e uma geometria, na qual vou usar PointField. Ficando assim:

# models.py
from django.db import models
from djgeojson.fields import PointField


class Fenomeno(models.Model):

    name = models.CharField(max_length=100, 
                            verbose_name='Fenomeno mepado')
    data = models.DateField(verbose_name='Data da observação')
    hora = models.TimeField()
    geom = PointField()

Pronto, já temos o modelo da 'tabela de dados "geográficos"'. Lembrando que no temos todo o poder de uma base de dados, mas sim, uma construção em json para minimamente armazenar y validar dados geográficos. Contudo, esse modelo ainda não foi "commitado"/"registrado" para/na a nossa base. Para isso:

manage makemigrations
manage migrate

O makemigrations analisa o models.py e o compara com a versão anterior identificando as alterações e criando um arquivo que será executado pelo migrate, aplicando tais alterações ao banco de dados.

Mas antes, [e o] teste~~!~~?

Pois é, eu adoraria apresentar isso usando a abordagem Test Driven Development (TDD). Mas, talvez pela falta de prática, conhecimento e etc, vou apenas apontar onde e como eu testaria esse sistema. Faço isso como uma forma de estudo, mesmo. Também me pareceu complicado apresentar a abordagem TDD em um artigo, já que a mesma se faz de forma incremental.

Sobre TDD

Soube do TDD em um encontro no Rio de Janeiro, chamado DOJORio. Ainda que eu só tenha tido a oportunidade de ir uma vez, e do fato de quando eu ter ido, termos feito o Code Dojo em JavaScript, me interessou bastante essa abordagem. Claro, com o Henrique Bastos e toda a comunidade do Welcome to The Django ví que essa abordagem tanto filosófica como técnica. É praticamente "Chora agora, ri depois", mas sem a parte de chorar. Pq com o tempo as coisas ficam mais claras... Alguns pontos:

  • O erro não é para ser evitado. Logo,
  • Entenda o que você quer do sistema e deixe o erro te guiar até ter o que espera;
  • Teste o comportamento esparado e não cada elemeto do sistema

Sem mais delongas:

O que testar?

Vamos usar o arquivo tests.py e criar nossos testes lá. Ao abrir vocês vão ver que já está o comando importando o TestCase.

Mas o que vamos testar?

Como o objetivo do projeto é criar um sistema qualquer com dados geográficos, vou me ater em testar a inserção de dados, entendendo, com isso, que o meu model está coerente com o que eu desejo.

Para ambos os casos, vou criar objeto do meu modelo Fenomeno, no setUp, para não ter que criá-lo sempre que for fazer um teste simulando a interação com a base de dados. E nessa carga de dados geográficos, fica claro a estrutura dos dados geojson: um dicionário com a chave type e coordinates, sendo a primeira responsável por identificar o tipo do dado e a última, uma lista de dois valores numéricos.

from django.test import TestCase
from mapProj.core.models import Fenomeno


class ModelGeomTest(TestCase):
    def setUp(self):
        self.fenomeno = Fenomeno.objects.create(
            name='Arvore',
            data='2020-11-06',
            hora='09:30:00',
            geom={'type': 'Point', 'coordinates': [0, 0]}
        )

    def test_create(self):
        self.assertTrue(Fenomeno.objects.exists())

⚠️ Reparem que:

  1. Para realizar o teste eu preciso importar o models da app em questão;
  2. No test_create() eu testo se existem objetos inseridos no model Fenomeno. Logo, testo se o dado criado no setUP foi corretamente incorporado no banco de dados.

Esse último ponto é interessante pois, ao inserir o dado da forma como está sendo feita (usando o método create() - e aconteceria o mesmo se estivesse usando o save()), sem usar um formulário do django, apenas será validado se o elemento a ser inserido é condizente com o tipo de coluna no banco de dados. Ou seja, o campo geom será salvo com sucesso sempre que seja passado um valor em json, mesmo que não necessariamente um geojson.

Esse fato é importante para reforçar o entendimento de que o djgeojson implementa classes de alto nível a serem trabalhados em views e forms. No banco, mesmo, temos um campo de json. E isso é que o faz simples. Não é preciso ter todo o "aparato" GIS instalado no seu servidor para poder usá-lo.

Registrando modelo no admin

Para facilitar, vou usar o django-admin. Trata-se de uma aplicação já criada onde basta registrar os modelos e views que estamos trabalhando para termos uma interface "frontend" genérica.

#admin.py
from django.contrib import admin
from mapProj.core.models import Fenomeno

admin.site.register(Fenomeno)

Add statics urls

STATIC_URL = '/static/'
MEDIA_URL = '/media/'
MEDIA_ROOT = BASE_DIR
pip install geojson

geojson

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Python 94.2%
  • JavaScript 4.1%
  • Other 1.7%