Exemplo em Django – parte 3

django-3_abertura

Prosseguindo com o desenvolvimento da “Agenda de Eventos”. A segunda parte tratou do modelo de dados da aplicação (ou simplesmente modelo), apresentou o Django ORM e cuidou de configurar do módulo de administração — lembrando que preferi ser breve mas que ainda voltarei a este assunto.

Nesta parte a construção efetiva da aplicação com a criação dos demais componentes do modelo MVC MTV.

Antes de começar…

Uma novidade! Já que a quantidade de arquivos aumentou, disponibilizei os arquivos em um repositório no GitHub, logo, basta cloná-lo:

$ git clone https://github.com/plainspooky/django-agenda_de_eventos.git
Cloning into 'django-agenda_de_eventos'...
remote: Counting objects: 44, done.
remote: Compressing objects: 100% (33/33), done.
remote: Total 44 (delta 5), reused 44 (delta 5), pack-reused 0
Unpacking objects: 100% (44/44), done.

Você pode continuar utilizando o ambiente criado na primeira parte ou recriá-lo dentro do diretório “./django-agenda_de_eventos” e neste caso repita os passos:

$ cd django-agenda_de_eventos
$ virtualenv --python $( which python3 ) py3
...
Installing setuptools, pkg_resources, pip, wheel...done.
$ source py3/source/activate

Para instalar as dependências do programa, faça:

$ pip install -r requirements.txt
...
Installing collected packages: pytz, Django
Successfully installed Django-2.0.4 pytz-2018.4

Para usar o banco de dados que estava sendo utilizado, copie o arquivo “db.sqlite3” para o repositório mas desejando criar uma nova base, use python manage.py migrate e depois importe esta maçaroca de dados aqui:

 

E não esqueça de usar python manage.py createsuperuser para recriar o superusuário da interface de administração! 🙂

ATENÇÃO : Para visualizar os arquivos do repositório na versão em que eles são citados aqui use git checkout parte-3 e git checkout master para voltar à última versão.

Gabarito — templates

Sendo um framework para aplicações web o Django necessita de um jeito fácil para criar dinâmicamente arquivos HTML. E a forma mais prática de fazê-lo é através do uso de templates contendo código HTML e também uma sintaxe específica para cuidar da inserção de conteúdo.

Especificamente no caso do Django o básico desta sintaxe é a seguinte:

  • {{...}} : Conteúdo de variáveis e com a possibilidade de utilizar filtros para a manipulação de conteúdo² e
  • {%...%} : Comandos específicos para comparar valores, executar laços, inserir outros gabaritos etc.

Os arquivos podem ter qualquer extensão e ficam por padrão no diretório “templates” — neste caso em “./events/templates”.

Arquivos estáticos

Os arquivos que não precisam ser interpretados pelo Django, ou seja, imagens, arquivos de estilo CSS, programas em JavaScript etc, ficam por padrão no diretório “static” — no caso em “./events/static”.

Criação do gabarito

django-3_gabarito

Montei um arquivo HTML a partir de um dos exemplos em Bootstrap 4 disponíveis e depois o segmentei em arquivos menores:

  • header.html” : Contendo o cabeçalho do HTML com CSS e todo o resto;
  • navbar.html” : A barra de navegação com nome do programa e também seu menu (por enquanto desabilitado);
  • footer.html” :A parte final do HTML com a carga do JavaScript e a finalização do arquivo.

Eles são a parte repetida das páginas e são utilizados na composição das páginas que fazem parte da aplicação:

  • day.html” : Exibe os eventos dentro de um dia específico;
  • events,html” : Lista todos os eventos cadastrados na aplicação e
  • show.html” : Mostra um evento específico.

E já que o WordPress não é lá muito amigável com HTML dentro das publicações e para não ficar replicando código sem necessidade, não os colocarei nesta parte, mas usarei alguns trechos para ajudar a explicar as visões.

(¹) Estou usando o termo gabarito ao invés de simplesmente citar “modelo” para justamente não confundir com modelo de dados.

(²) Funcionando de modo parecido com diversos outros programas escritos em Python como o Ansible (implementado com Jinja2), Bottle e até mesmo o Inliner! 😀

Visões

As visões servem para encapsular a lógica responsável pelo processamento das requisições feitas pelo usuário e uma eventual resposta. Elas podem ser implementadas como se fossem funções ou então como classes. Por enquanto esta aplicação contém três visões implementadas como funções.

Todos os eventos

Se nenhum parâmetro³ for passado ao programa ele usará o gabarito “events.html” para mostrar todos os eventos cadastrados.

def index(request):
    context = { 
        'events': Event.objects.order_by('-date',
                                         '-priority', 'event'),
    }
    return render(request, 'events.html', context)

Através do Django ORM é feita uma consulta ao bando de dados para coletar todos os objetos e ordená-los por data (em ordem decrescente — repare no “-” na frente ele serve para inverter a ordem), prioridade (ordem decrescente) e descrição do evento (ordem crescente, alfabética). Esta consulta, ou QuerySet como é referenciada na documentação, é armazenada na chave ‘events’ da variável ‘context’.

O método render() cuida de montar a página HTML para o usuário utilizando os comandos dentro do gabarito “events.html” que tem a seguinte estrutura.

{% if events|length > 0 %}
    «início da tabela e cabeçalho»
    {% for event in events %}
         «linha da tabela»
    {% endfor %}
    «fim da tabela»
{% else %}
    « aviso de que não há eventos »
{% endif %}

Com o filtro length verifico o total de elementos dentro de events, sendo maior que zero é criada uma tabela que será populada iterando cada elemento de events através do comando for (que é análogo ao do Python).

Dentro da tabela, a troca da cor é feita utilizando as classes de contexto do Bootstrap e escolhida de acordo com prioridade do evento.

{% if event.priority == '1' %} table-success
{% elif event.priority == '2' %} table-warning
{% elif event.priority == '3' %} table-danger
{% else %} table-default
{% endif %}

A data é devidamente formatada através do filtro date:

{{ event.date|date:"d-m-Y" }}

No final é informado o total de eventos.

Você tem {{ events|length }} evento{{ events|pluralize }}
registrado{{ events|pluralize }}.

Aqui o filtro pluralize se encarrega de colocar, ou não, um “s” caso o total de objetos na variável seja maior que um.

Evento específico

A visualização do evento específico lembra um pouco a utilizada para todos os eventos.

def show(request, id):
    context = {
        'event': Event.objects.get(id=id),
    }
    return render(request, 'show.html', context)

As diferenças estão no fato de que ela recebe um parâmetro pela URL, o id, que é usado para recuperar o evento específico no banco de dados. E então chama o gabarito “show.html” para gerar a página HTML.

Eventos do dia

Esta visão é a mais complexa das demais, ela recebe três parâmetros pela URLyear, month e day — utilizados para compor a data que será exibida para o usuário como também os valores utilizados para a interface de navegação deste gabarito para selecionar a data anterior e seguinte.

def day(request, year, month, day):
    day = datetime(year, month, day)
    context = {
        'today': localdate(),
        'day': day,
        'previous': day - timedelta(days=1),
        'next': day + timedelta(days=1),
        'events': Event.objects.filter(
            date="{:%Y-%m-%d}".format(day)).order_by('-priority',
                                                     'event')
 }
 return render(request, 'day.html', context)

Para o cálculo das datas é utilizada o método timedelta() do módulo datetime para calcular os dias anterior e próximo da data informada, o atributo ‘today’ ainda não é utilizado e sua função ficará clara quando o menu do programa for incluído aos gabaritos.

E a QuerySet usada consiste em um subconjunto daquela utilizada na listagem de todos os eventos mas contendo apenas os eventos de uma data específica.

(³) O parâmetro request é obrigatório e contém as informações do protocolo HTTP.

Urls

As urls consistem em um mapeamento que cuida de direcionar cada requisição recebida pelo servidor HTTP para uma determinada visão dentro das aplicações do projeto. Elas podem ser configuradas dentro do arquivo “./Agenda/urls.py” porém, por convenção, cria-se um arquivo próprio por aplicação, neste caso o “./events/url.py”.

Para incluir a lista de URL específicas da aplicação acrescente as partes grafadas ao arquivo de URL do projeto, o “./Agenda/urls.py”.

from django.contrib import admin
from django.urls import include, path

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('events.urls')),
]

Então criar o arquivo “./events/urls.py” — o “events.urls”.

from django.urls import path
from . import views

urlpatterns = [
    path('', views.index, name='agenda-events-all'),
    path('', views.show, name='agenda-events-show'),
    path('//', views.day, name='agenda-events-day'
    ]

O primeiro parâmetro é a URL recebida pelo servidor HTTP, respectivamente uma string vazia (nenhum parâmetro), um número inteiro e três números inteiros separados por uma barra — elas correspondem aos parâmetros de entrada das respectivas funções da visão que corresponde ao segundo parâmetro.

O terceiro parâmetro, ‘name’, as identifica. Isto é utilizado para a geração das URL dentro dos gabaritos e assim não codificar as URL diretamente.

{% url 'agenda-events-show' event.id %}

Neste caso ela criará com o nome correto a URL para acesso a um evento específico.

Fim desta parte

django-3_novo-evento

Como as alterações já foram feitas não há necessidade de atualizar o repositório do Git e neste ponto a aplicação já exibe perfeitamente os eventos cadastrados dentro dela, listando-os de diversos modos. O problema é que a manutenção dos eventos (inclusão, exclusão e alteração) só está disponível através da interface de administração do Django mas isto será resolvido na próxima parte.

Até!

Anúncios

Um comentário sobre “Exemplo em Django – parte 3

  1. Pingback: Exemplo em Django – parte 4 | giovannireisnunes

Os comentários estão desativados.