A maneira mais eficaz de dominar o Django, ou qualquer outra competência, é colocar em prática o conhecimento adquirido através da criação de projetos funcionais.
O Django é o framework de desenvolvimento web em Python mais amplamente adotado. A sua vasta gama de funcionalidades integradas e a grande quantidade de pacotes de terceiros tornaram-no um dos frameworks web mais apreciados mundialmente.
Destaca-se pela sua rapidez, fiabilidade e inúmeras funcionalidades incorporadas. Por exemplo, possui um sistema de autenticação abrangente, que permite que você direcione a sua atenção para os recursos essenciais da sua aplicação. Além disso, é possível instalar pacotes externos para executar tarefas ainda mais complexas, como o Django-allauth, que possibilita o registro de utilizadores através das suas contas de redes sociais.
No entanto, é importante reconhecer que, devido à sua dimensão, o Django pode, por vezes, ser desafiador para iniciantes.
Assim, neste artigo, iremos criar, passo a passo, uma aplicação Django totalmente operacional.
Ao concluir este tutorial, você terá:
- Construído uma aplicação de encurtamento de URLs.
- Compreendido o padrão Django MVT.
- Aprendido o processo de trabalho para criar um projeto.
Requisitos Essenciais
Os requisitos apresentados a seguir são opcionais, mas auxiliarão na compreensão do tutorial. No entanto, se você não tiver experiência prévia com algum deles, não se preocupe. O ponto de partida é o mais crucial.
- Conhecimento básico de comandos UNIX (ls, cd, rm, touch).
- Compreensão elementar de classes e funções em Python.
- Python instalado em seu computador (essencial, mas convém mencionar).
- Seria vantajoso se já tivesse desenvolvido algo com o Django.
Todo o código desenvolvido estará acessível neste repositório Github.
Agora que você tem uma base sólida, vamos nos aprofundar no assunto.
Definição do Projeto
Neste tutorial, você criará um encurtador de URLs. Basicamente, um encurtador de URLs é um serviço que converte um endereço web longo em um mais curto.
Por exemplo, se desejar partilhar um tweet e incluir um link para o seu site, mas estiver a lidar com uma limitação de caracteres, pode recorrer a um encurtador de URLs.
Vamos analisar com um esquema.
Como pode observar, o encurtador de URLs recebe um endereço longo e gera um curto. É precisamente isso que iremos construir hoje.
Através deste projeto, você praticará a aplicação do padrão MVT, aprenderá as bases do design de bases de dados com os modelos Django, e aprenderá como exibir informações para o utilizador através de views, URLs e templates.
Estrutura de um Projeto Django
Em geral, um site Django é construído sobre um único projeto e várias aplicações distintas. Cada uma dessas aplicações possui uma funcionalidade específica e opera de forma independente.
Vamos considerar uma aplicação web complexa como o Stackoverflow. A sua funcionalidade assenta em dois pilares principais:
- Gestão de utilizadores: login, logout, reputação, permissões.
- Fórum: Perguntas, respostas, tags, filtros.
Assim, seguindo a estrutura de um site Django, o projeto seria denominado StackOverflow, que incluiria duas aplicações principais: a aplicação de utilizadores e a aplicação do fórum.
Cada uma dessas aplicações opera com autonomia. Ou seja, ambas contêm o código essencial para o seu funcionamento adequado.
Isso inclui modelos (estrutura da base de dados), views (requisições e respostas), padrões de URL específicos e, claro, templates e arquivos estáticos (imagens, CSS, JavaScript). Isto significa que qualquer aplicação Django pode ser reutilizada, uma vez que é capaz de operar por si só.
Em síntese, um projeto refere-se a um conjunto de configurações e aplicações destinadas a criar uma aplicação web. Por outro lado, uma aplicação Django é parte de um projeto, sendo autossuficiente (possui tudo o que precisa para operar) e tendo como propósito executar uma operação específica.
Configuração de um Projeto Django
Nesta seção, você irá configurar um projeto Django. Para tal, irá utilizar diferentes ferramentas como um ambiente virtual para organizar as dependências do Python e os scripts Django mais importantes: django-admin e manage.py.
Ambiente Virtual
É sempre recomendável trabalhar com ambientes virtuais ao desenvolver aplicações com Django. É a forma mais eficaz de manter um conjunto específico de dependências. Contudo, o seu principal objetivo é isolar os pacotes de desenvolvimento dos globais.
Portanto, vamos criar um ambiente virtual com o Python, através do comando embutido:
python -m venv .venv
Este comando utiliza o comando python -m ou python –mod. Essencialmente, ele executa um módulo ou biblioteca, à semelhança de um script. No contexto deste comando, venv é a biblioteca que estamos a executar e .venv refere-se ao nome do ambiente virtual que pretendemos criar.
Por outras palavras, este comando significa:
“Ei, Python, executa como um script a biblioteca integrada venv e cria um virtualenv com o nome .venv.”
Agora, é altura de ativar o ambiente virtual que acabamos de criar, com o seguinte comando:
source .venv/bin/activate
Para confirmar que não possui nenhum pacote instalado no novo venv, execute:
pip freeze
Se o ambiente virtual foi ativado corretamente, não deverá obter qualquer resultado. Isso ocorre porque ainda não instalamos nada.
Integração com o Django
Para desenvolver a nossa aplicação de encurtamento de URLs, vamos começar por instalar o pacote Django. Sendo o Django um pacote de terceiros, precisamos de o instalar através do Pip (Pip Installs Packages).
$ pip install django Collecting django Downloading Django-3.2.1-py3-none-any.whl (7.9 MB) |████████████████████████████████| 7.9 MB 344 kB/s Collecting asgiref<4,>=3.3.2 Using cached asgiref-3.3.4-py3-none-any.whl (22 kB) Collecting sqlparse>=0.2.2 Using cached sqlparse-0.4.1-py3-none-any.whl (42 kB) Collecting pytz Using cached pytz-2021.1-py2.py3-none-any.whl (510 kB) Installing collected packages: asgiref, sqlparse, pytz, django Successfully installed asgiref-3.3.4 django-3.2.1 pytz-2021.1 sqlparse-0.4.1
Nota: Lembre-se que $ nada mais é do que o símbolo da shell.
Para confirmar se a instalação foi bem-sucedida, verificamos novamente os pacotes instalados no nosso venv:
$ pip freeze asgiref==3.3.4 Django==3.2.1 pytz==2021.1 sqlparse==0.4.1
Não se preocupe se as versões que obtiver forem diferentes das minhas. Se o Django ainda estiver na versão 3.x, pode prosseguir sem problemas.
Criação de um Projeto Django
Após a instalação do Django, é altura de construir a estrutura do site de encurtamento de URLs. Lembra-se do que é um projeto Django? Vamos criar um, executando o seguinte comando:
django-admin startproject config
Analisando este comando, django-admin é uma ferramenta de linha de comandos que executa todas as tarefas necessárias para criar um projeto Django. A parte “startproject” é o comando executado pela ferramenta django-admin e config é o nome do projeto que iremos criar.
É importante destacar que config pode ter o nome que você quiser. A razão pela qual uso config como nome deste projeto é por uma questão de conveniência. É útil alternar entre projetos e manter a mesma convenção de nomenclatura. Por isso, não hesite em utilizar outros nomes de projetos sempre que pretender.
Como pode constatar, agora tem uma pasta config/ e, dentro desta, existem vários ficheiros. Mais adiante, analisaremos a estrutura de ficheiros do projeto. Por enquanto, vamos entrar no diretório do projeto e executar o servidor local.
cd config/
O arquivo mais importante que irá utilizar é o script manage.py. Possui a mesma funcionalidade do django-admin, mas a principal vantagem de o utilizar é que permite gerir as configurações ao executar o projeto.
Agora, vamos verificar se tudo está a funcionar corretamente.
python manage.py runserver
Criação da Aplicação de Encurtamento de URLs
É altura de criar a aplicação principal do projeto. Irá utilizar o arquivo manage.py para realizar esta tarefa.
python manage.py startapp urlshortener
Isto cria uma aplicação Django, com o nome urlshortener. Se executar o comando tree, obterá algo semelhante a isto:
. ├── config │ ├── asgi.py │ ├── __init__.py │ ├── settings.py │ ├── urls.py │ └── wsgi.py ├── manage.py └── urlshortener ├── admin.py ├── apps.py ├── __init__.py ├── migrations │ └── __init__.py ├── models.py ├── tests.py └── views.py
Vamos clarificar os diferentes arquivos criados até este momento. “config” é o nome do nosso projeto e é assim chamado apenas por convenção. Dentro do config, você encontra o settings.py, que é o arquivo onde define todas as configurações do seu projeto. O urls.py é a configuração geral das URLs dentro do projeto. Define os caminhos de URL de todas as aplicações dentro do projeto.
Não se preocupe muito com os arquivos asgi.py e wsgi.py. São arquivos que permitem configurar a sua aplicação na fase de implementação.
O manage.py é o script Python que possibilita a execução de todos os comandos disponíveis no Django-admin.
Ao analisar o interior da pasta urlshortener, que é o nome da aplicação que acabou de criar, pode notar a existência de uma pasta invulgar denominada “migrations/” e alguns outros arquivos que são cruciais para a lógica de qualquer aplicação.
O arquivo apps.py é onde reside a configuração da aplicação. Normalmente, não o altera, exceto se estiver a realizar operações bastante avançadas.
O admin.py é onde regista os seus modelos para os tornar visíveis dentro do painel de administração do Django.
O models.py é o mais importante. Dentro deste módulo, deve definir os modelos que (grosso modo) são a forma como os dados são armazenados. Saberá mais sobre os modelos mais tarde.
A pasta migrations/ é onde as migrations do Django são armazenadas. Faremos uma análise aprofundada mais adiante.
O arquivo tests.py é onde os testes são guardados. Não abordaremos os testes neste tutorial.
O views.py é o arquivo que armazena as views. Essencialmente, define como o utilizador irá interagir com todos os aspetos da sua aplicação.
Instalação de uma Aplicação Django
Antes de prosseguir, abra o arquivo settings.py e modifique a variável INSTALLED_APPS, adicionando a aplicação urlshortener.
# Application definition INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', # Custom apps 'urlshortener', ]
Este é um processo de rotina quando cria uma aplicação. Portanto, sempre que o fizer, não se esqueça de o instalar nas configurações do projeto.
Compreendendo o Padrão MVT
O padrão Model, View, Template (Modelo, View, Template) é o padrão de design de software que os desenvolvedores do Django utilizam para construir aplicações web.
Baseia-se em três conceitos principais: Model (dados), View (interação do utilizador com os dados) e Template (como os utilizadores veem os dados).
Os Models são classes Python, que definem todos os campos e comportamentos dos dados que deseja armazenar. Normalmente, cada modelo corresponde a uma tabela específica na base de dados.
As Views, na sua forma mais simples, são chamadas que recebem uma solicitação do utilizador e geram uma resposta. Entre este processo, ocorre a lógica de negócios. Sei que o conceito “lógica de negócios” pode ser um pouco abstrato, então deixe-me explicar exatamente o que significa. A lógica de negócios é a forma como os dados são criados, armazenados e excluídos, e nada mais.
Por fim, os Templates são documentos de texto (normalmente HTML) que são exibidos aos utilizadores. O seu objetivo é apresentar os dados da forma mais limpa possível. O Django incorpora uma mini-linguagem chamada Linguagem de Templates do Django (DTL) que permite incorporar parte do poder do Python em documentos de texto.
Criação do Modelo Shortener
Após uma rápida compreensão do padrão MVT, vamos começar a construir o encurtador de URLs do Django a partir do zero.
Inicialmente, vamos definir o modelo encurtador dentro do arquivo models.py:
''' Url shortener model ''' from django.db import models # Create your models here. class Shortener(models.Model): ''' Creates a short url based on the long one created -> Hour and date a shortener was created times_followed -> Times the shortened link has been followed long_url -> The original link short_url -> shortened link https://domain/(short_url) ''' created = models.DateTimeField(auto_now_add=True) times_followed = models.PositiveIntegerField(default=0) long_url = models.URLField() short_url = models.CharField(max_length=15, unique=True, blank=True) class Meta: ordering = ["-created"] def __str__(self): return f'{self.long_url} to {self.short_url}'
Reconheço que é uma classe bastante extensa, com muita coisa incomum a acontecer, mas não se preocupe. Iremos analisar cada parte importante passo a passo.
Explicação do Modelo
Em primeiro lugar, importamos o módulo models. Este módulo contém todas as funcionalidades de que precisamos para criar um modelo Django.
Analisando o modelo “Shortener”, a primeira coisa a notar é que ele estende models.Model. Na verdade, qualquer modelo em qualquer aplicação Django deve ser uma subclasse da classe models.Model.
Em seguida, definimos todos os campos que o modelo terá na base de dados. O campo “created” representa a data e hora em que o link encurtado é criado, portanto, utilizamos DateTimeField para criar este tipo de funcionalidade. Usamos o argumento auto_now_add=True porque queremos que o campo seja alterado apenas quando a instância for criada.
O segundo campo, times_followed, refere-se ao número de vezes que a URL encurtada foi utilizada. É um PositiveIntegerField e especificamos um valor padrão de zero. Isso significa que sempre que uma instância criar o campo times_followed, o Django irá preencher este campo com 0.
Por outro lado, long_url refere-se à URL que o utilizador insere. É um URLField, pois pretendemos que o utilizador insira apenas caracteres do tipo: http://seusite.com.
O último campo é short_url e possui detalhes interessantes. Especificamos que só pode ter 15 caracteres, deve ser único, o que significa que não pode haver elementos repetidos neste campo. Por fim, indicamos que pode ser deixado em branco, o que significa que ao trabalhar com formulários, o utilizador não necessitará de escrever o seu próprio código abreviado.
A classe interna Meta, indica-nos como a classe se deve comportar, e definimos que a ordenação (ao invocar Shortener.objects.all()) dos objetos de encurtamento será ordenada pelos mais recentes.
O método __str__ define como o modelo deve ser impresso. Portanto, se tivermos um objeto com long_url = “https://etechpt.com.com/” e a parte abreviada “123456”, e o imprimirmos:
https://etechpt.com.com/ to 123456
Agora, é altura de procurar uma forma de guardar o link curto de forma aleatória.
Criação da Funcionalidade de Encurtamento
Vamos criar duas funções personalizadas. A primeira irá gerar um código aleatório e a segunda irá evitar a obtenção de códigos aleatórios repetidos do modelo Shortener. Para tal, crie um arquivo utils.py dentro da aplicação “urlshortener”.
touch utils.py
Dentro deste arquivo, vamos utilizar a função choice do módulo interno random. Isto facilita a tarefa de escolher caracteres aleatórios para criar o código.
''' Utilities for Shortener ''' from django.conf import settings from random import choice from string import ascii_letters, digits # Try to get the value from the settings module SIZE = getattr(settings, "MAXIMUM_URL_CHARS", 7) AVAIABLE_CHARS = ascii_letters + digits def create_random_code(chars=AVAIABLE_CHARS): """ Creates a random string with the predetermined size """ return "".join( [choice(chars) for _ in range(SIZE)] )
Como pode observar, esta função retorna uma string aleatória com o comprimento especificado no arquivo de configurações ou 7 por defeito. Está a utilizar a função getattr para obter uma variável do módulo de configurações, mas sem gerar um erro se a variável não for especificada.
Vamos fazer algumas contas. Se tivermos 7 lugares onde pode haver até 62 caracteres disponíveis para cada lugar, as possíveis permutações são:
Assim, com base nestes cálculos rápidos, a parte abreviada pode ser preenchida com até 2,5 triliões de códigos diferentes. Portanto, podemos ignorar a questão de ficar sem URLs abreviadas aleatórias.
Embora possa existir tanta permutação, há uma pequena probabilidade de obter partes encurtadas repetidas. Isso é um problema, uma vez que configuramos o campo shorted_url para ser único. É por isso que a seguinte função é tão útil:
def create_shortened_url(model_instance): random_code = create_random_code() # Gets the model class model_class = model_instance.__class__ if model_class.objects.filter(short_url=random_code).exists(): # Run the function again return create_shortened_url(model_instance) return random_code
Vamos analisar o que está a acontecer aqui. A função recebe como argumento uma instância do modelo “Encurtador”. Primeiro, a função gera um código aleatório utilizando create_random_code. Em seguida, obtém a classe do modelo e verifica se existe algum outro objeto que possua a mesma short_url. Se existir, a função executa-se novamente, mas se tudo estiver bem, ela retorna o random_code.
Mais tarde, irá interagir com a shell para analisar esta função de perto.
Após criar a função de utilidade, vamos utilizá-la para criar códigos aleatórios no modelo de encurtador.
Modificação do Método de Salvamento
No final da classe “Shortener”, irá modificar o método de salvamento do modelo. O método save é invocado sempre que um objeto é guardado na base de dados, por isso vamos analisar como o utilizar aqui.
# Import the function used to create random codes from .utils import create_shortened_url # At the end of the Shortener model def save(self, *args, **kwargs): # If the short url wasn't specified if not self.short_url: # We pass the model instance that is being saved self.short_url = create_shortened_url(self) super().save(*args, **kwargs)
O método save está a ser sobreposto, o que significa que está a introduzir uma nova funcionalidade num método pai preexistente. Basicamente, ele diz ao Django que sempre que um objeto “Shortener” é guardado e a short_url não é especificada, esta deve ser preenchida com um código aleatório.
Execução de Migrações
Agora, é altura de efetuar e executar as migrações do modelo Shortener. Para tal, execute os seguintes comandos na pasta raiz do projeto:
$ python manage.py makemigrations Migrations for 'urlshortener': urlshortener/migrations/0001_initial.py - Create model Shortener $ python manage.py migrate Operations to perform: Apply all migrations: admin, auth, contenttypes, sessions, urlshortener Running migrations: ...... # Apply the URL shortener migrations Applying urlshortener.0001_initial... OK
Por enquanto, não precisa de se preocupar com o que são as migrações. Tenha apenas em mente que, ao executar estes dois comandos, o Django cria um arquivo de base de dados db.sqlite, com base nos modelos que definiu.
Vamos criar alguns objetos utilizando a shell do Django.
$ python manage.py shell >>> from urlshortener.models import Shortener >>> s = Shortener(long_url="https://etechpt.com.com") >>> s.short_url '' >>> s.save() >>> s.short_url 'kdWFVIc' >>> s.long_url 'https://etechpt.com.com' >>> print(s) https://etechpt.com.com to kdWFVIc
É assim que todos os objetos de encurtamento irão funcionar.
Criação de Views
Como referi anteriormente, uma view é uma função simples que recebe uma solicitação e retorna uma resposta. Assim, vamos analisar como criar uma view simples de “olá mundo”.
Modelo Básico de Resposta
Dentro do arquivo “urlshortener/views.py”, crie uma função home_view:
''' Shortener views ''' from django.shortcuts import render, get_object_or_404 # We will use it later from django.http import HttpResponse # Create your views here. def home_view(request): return HttpResponse("Hello world")
Esta função retorna uma simples mensagem “Hello world”. Mais tarde, verá como se apresenta no navegador. Agora, crie um arquivo “urls.py”, onde ficarão todos os padrões de URL da aplicação.
touch urls.py
Adicione o seguinte código:
''' Urls for shortener app urlshortener/urls.py ''' from django.urls import path # Import the home view from .views import home_view appname = "shortener" urlpatterns = [ # Home view path("", home_view, name="home") ]
A variável appname declara (como o próprio nome sugere) o namespace da aplicação urlshortener.
Explicando de forma breve, estamos a importar a função path, que retorna um elemento para incluir nos urlpatterns da aplicação. O atributo name é o namespace do caminho, que pode ser invocado dentro dos templates, caso seja necessário.
Agora, vamos modificar as URLs gerais do projeto:
# config/urls.py from django.contrib import admin from django.urls import path, include urlpatterns = [ path('admin/', admin.site.urls), # Shortener Urls path('', include('urlshortener.urls')) ]
Agora, vamos executar o servidor novamente:
python manage.py runserver
Se executar o servidor, receberá uma simples mensagem “Hello world”. Isso ocorre porque está a incluir os urlpatterns da aplicação de encurtamento de URLs no projeto geral.
Este é apenas um ponto de partida. Agora, é altura de criar um formulário para permitir que o utilizador crie as suas próprias URLs abreviadas.
Criação de Formulários
No Django, um Form é uma classe simples que possibilita a obtenção de dados do utilizador.
Irá criar um arquivo forms.py. É uma convenção armazenar todos os formulários da aplicação neste arquivo.
cd urlshortener/ touch forms.py
Dentro deste arquivo, irá criar uma classe “ShortenerForm” que herda de “ModelForm”.
''' Shortener Forms urlshortener/forms.py ''' from django import forms from .models import Shortener class ShortenerForm(forms.ModelForm): long_url = forms.URLField(widget=forms.URLInput( attrs={"class": "form-control form-control-lg", "placeholder": "Your URL to shorten"})) class Meta: model = Shortener fields = ('long_url',)
Trata-se de um formulário de modelo, uma vez que o seu propósito é criar um objeto de modelo a partir dos dados do utilizador. Utilizamos também o argumento widget, que nos permite especificar o atributo “class” (classe em CSS, não em Python). Isso ocorre porque iremos estilizar a aplicação com o Bootstrap mais tarde.
Conclusão das Views
Depois de construir os formulários, é altura de criar a lógica de negócios final da aplicação.
Navegue até o arquivo views.py dentro da aplicação de encurtamento e modifique a view home_view. Pode consultar o repositório Github para ter uma ideia da estrutura do projeto neste ponto.
Existem duas views para a aplicação de encurtamento de URLs:
Vamos começar com a View Inicial, que é a mais complexa. Precisará de importar o modelo e o formulário Shortener. Continuaremos a utilizar uma função, uma vez que pretendo que compreenda todo o fluxo de dados da View. Além disso, irá utilizar o caminho para um template (que ainda não foi criado).
View Inicial
''' Shortener views ''' from django.shortcuts import render # We will use it later from django.http import HttpResponse, Http404, HttpResponseRedirect # Model from .models import Shortener # Custom form from .forms import ShortenerForm # Create your views here. def home_view(request): template="urlshortener/home.html" context = {} # Empty form context['form'] = ShortenerForm() if request.method == 'GET': return render(request, template, context) elif request.method == 'POST': used_form = ShortenerForm(request.POST) if used_form.is_valid(): shortened_object = used_form.save() new_url = request.build_absolute_uri('/') + shortened_object.short_url long_url = shortened_object.long_url context['new_url'] = new_url context['long_url'] = long_url return render(request, template, context) context['errors'] = used_form.errors return render(request, template, context)
A View baseia-se em dois condicionais:
Uma maneira engenhosa de obter a URL completa do site dinamicamente é utilizando o método build_absolute_uri do objeto de requisição.</p