Django

Entendendo o MTV do Django

Agora que já sabemos como criar um projeto e como criar uma app com o Django, já estamos prontos para criar nossa primeira aplicação com o framework. Porém, antes disso, precisamos entender como funciona a arquitetura do framework, o que veremos neste artigo.

Arquitetura do Django

A arquitetura do Django é relativamente simples. Basicamente, um projeto Django possui como padrão de projeto o MTV (Model, Template, View), que servem para:

  • Model: Mapeamento do banco de dados para o projeto;
  • Template: Páginas para visualização de dados. Normalmente, é aqui que fica o HTML que será renderizado nos navegadores;
  • View: Lógica de negócio. É aqui que determinamos o que irá acontecer em nosso projeto.

Toda esta arquitetura é interligada e conversam entre si. Uma depende da outra para realizar um determinado serviço e, no final, executar a tarefa que o usuário solicitou. A imagem abaixo descreve exatamente como este processo funciona:


Como visto na imagem, quando o usuário faz uma requisição pelo browser, utilizando uma rota, é executado um método das Views, que utiliza os Models para acessar o banco de dados e retornar as informações. Estas informações são renderizadas pela camada de Template e, finalmente, é renderizado para o usuário pelo navegador.

Django - Fundamentos
Curso de Django - Fundamentos
CONHEÇA O CURSO

Toda esta arquitetura se assemelha bastante com o padrão MVC (Model, View, Controller), utilizado em diversos outros frameworks, como o Laravel, Zend Framework e muitos outros. Comparado ao MVC, as camadas do padrão MTV podem ser consideradas como podemos ver abaixo:

  • M (MTV) = M (MVC): Estas duas camadas possuem a mesma responsabilidade, mapeamento do banco de dados para o projeto;
  • T (MTV) = V (MVC): Estas camadas possuem a mesma responsabilidade, exibir informações para o usuário da aplicação, normalmente utilizando páginas HTML;
  • V (MTV) = C (MVC): Estas duas camadas, apesar de possuírem responsabilidades parecidas, conceitualmente, apresentam algumas diferenças.

No próprio FAQ do Django, há uma área onde os desenvolvedores explicam as diferenças conceituais e o motivo de nomear a camada de visualização de dados como templates e de views a camada de lógica de acesso.

Well, the standard names are debatable.
In our interpretation of MVC, the “view” describes the data that gets presented to the user. It’s not necessarily how the data looks, but which data is presented. The view describes which data you see, not how you see it. It’s a subtle distinction.
So, in our case, a “view” is the Python callback function for a particular URL, because that callback function describes which data is presented.
Furthermore, it’s sensible to separate content from presentation – which is where templates come in. In Django, a “view” describes which data is presented, but a view normally delegates to a template, which describes how the data is presented.
Where does the “controller” fit in, then? In Django’s case, it’s probably the framework itself: the machinery that sends a request to the appropriate view, according to the Django URL configuration.
If you’re hungry for acronyms, you might say that Django is a “MTV” framework – that is, “model”, “template”, and “view.” That breakdown makes much more sense.
At the end of the day, of course, it comes down to getting stuff done. And, regardless of how things are named, Django gets stuff done in a way that’s most logical to us.

Resumidamente, a equipe de desenvolvimento do framework entende que a camada view descreve quais dados serão apresentados ao usuário, não a forma (aparência) que eles serão exibidos. Portanto, no padrão MTV, uma view é uma função que retorna algo para uma solicitação, porque ela define apenas quais dados serão apresentados, não como serão mostrados.

Além disso, é sensato separar o conteúdo da apresentação (por questões de organização e padronização do código). É aí que entra camada template. Com os dados retornados pela view, a template fica responsável por definir a forma que esses dados serão apresentados, normalmente em páginas HTML.

Porém, onde o controller se encaixa? No Django, os desenvolvedores do framework entendem que esta camada é a própria estrutura do projeto. É este mecanismo que envia uma solicitação para a view adequada de acordo com a configuração de rotas do Django. E isso faz sentido! Se pararmos para pensar, o controlador da aplicação é o próprio conjunto de bibliotecas que compõe o projeto. A view é mais adequada a retornar os dados a serem visualizados, que serão exibidos ao usuário por meio de templates.

Agora que a arquitetura do Django ficou clara (espero :p), nós já estamos aptos a iniciar o desenvolvimento da nossa primeiro aplicação e, finalmente, programar utilizando este incrível framework. E é exatamente isso que veremos no próximo artigo. Até lá!

Criando um app com Django

O Django é um ótimo framework para desenvolvimento de aplicações web. Com ele, conseguimos construir aplicações de alto desempenho, prezando pela legibilidade e reaproveitamento de código.

Por padrão, um projeto Django é dividido em diversas apps. Cada app é responsável por um módulo da aplicação e permite uma maior organização e legibilidade do projeto. Neste artigo, então, veremos como criar e configurar uma app em um projeto Django.

Criando o projeto

O primeiro passo para criarmos nosso projeto é configurar nosso ambiente de desenvolvimento, conforme mostrado no artigo como configurar nosso ambiente de desenvolvimento com Django, já que precisamos de uma série de ferramentas para que tudo funcione corretamente.

Basicamente, a configuração do ambiente se resume em instalar o Python, o PIP e o PyCharm. Todas estas ferramentas são necessárias para que possamos desenvolver nossos projetos sem dor de cabeça.

Feito isso, o próximo passo é a criação do projeto, conforme mostrado no artigo como criar o primeiro projeto Django utilizando o PyCharm. Após criar o projeto e executá-lo, teremos a seguinte tela como resposta:

Django - Fundamentos
Curso de Django - Fundamentos
CONHEÇA O CURSO

Com o projeto criado, o próximo passo é criar nossa aplicação. Basicamente, o Django é dividido em diversas apps em um mesmo projeto. Isso facilita o reaproveitamento de código e organização do projeto como um todo.

Para criar uma app no Django, utilizamos o seguinte comando:

python manage.py startapp nome_da_app

Ao executar o comando acima (alterando o nome_da_app para o nome da sua aplicação), uma série de arquivos é criada:

Django - Módulo administrativo Django Admin
Curso de Django - Módulo administrativo Django Admin
CONHEÇA O CURSO

Estes arquivos são:

  • Diretório migrations: Diretório responsável por armazenar os arquivos de migração para o banco de dados de uma aplicação Django.
  • admin.py: Arquivo responsável por definir os models a serem utilizados no módulo administrativo do Django.
  • apps.py: Arquivo responsável pela configuração da app do projeto Django.
  • models.py: Arquivo responsável por definir os modelos da aplicação. Basicamente, um modelo é a representação das tabelas a serem criadas no banco de dados.
  • tests.py: Arquivo responsável por definir as regras de testes da aplicação.
  • views.py: Arquivo responsável por definir as regras de negócio do app.

Ao criar a aplicação, precisamos registrá-la no arquivo settings.py do projeto. Isso fará com que o projeto Django saiba que essa app faz parte do projeto e que ele pode gerenciá-la. Para fazer isso, no arquivo settings.py, adicionamos o nome da app no array INSTALLED_APPS, como podemos ver abaixo:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'app'
]

Feito isso, o projeto Django já sabe que a aplicação app faz parte do projeto e já estamos prontos para iniciar seu desenvolvimento, o que faremos no próximo artigo desta série 🙂

Até lá!

Compartilhando rotas entre apps no Django

Um projeto Django é composto por uma ou mais aplicações, que possui um arquivo de rotas. Agora imagine que tenhamos duas apps com rotas de mesmo nome ou que precisamos executar métodos de uma outra app … Como diferenciar cada rota dentro do projeto e como compartilhar as rotas entre as aplicações de um projeto? É o que veremos neste artigo.

Utilizando namespaces no Django

A compartilhação de rotas entre apps no Django é muito simples. A primeira coisa a se fazer é determinar o namespace daquele arquivo de rotas. Este namespace é o que define de onde a rota pertence (a qual app aquela rota foi criada).

Imagine que você tenha um projeto com duas (ou mais) aplicações e que há rotas nessas aplicações que são compartilhadas entre as apps. Para realizar este “compartilhamento”, precisamos definir o nome do namespace de cada arquivo de rotas. É este nome que identificará de onde a rota será chamada.

Para isso, no arquivo urls.py da app que queremos compartilhar as rotas, definimos a seguinte configuração no app_name:

from django.urls import path
from .views import *

app_name = 'admin_blog'

urlpatterns = [
    path('listar_posts/', listar_posts, name='listar_posts'),
    path('editar_post/<int:id>', editar_post, name='editar_post'),
    path('remover_post/<int:id>', remover_post, name='remover_post'),
    path('cadastrar_post/', cadastrar_post, name='cadastrar_post'),

]

É o conteúdo do app_name que determina como chamaremos as rotas externamente.

Django - Desenvolvimento de APIs REST
Curso de Django - Desenvolvimento de APIs REST
CONHEÇA O CURSO

Além disso, precisamos determinar que o conjunto de rotas da app possui o namespace ‘admin_blog’ no arquivo de rotas do projeto:

urlpatterns = [
    path('admin_blog/', include('admin_blog.urls', namespace='admin_blog')),
  #...
]

Invocando rotas em outras apps com Django

Agora que determinamos a configuração do app_name no arquivo de rotas da aplicação, podemos executá-las externamente. Para isso, a nomenclatura é a seguinte:

nome_definido_no_app_name:nome_da_rota

Sendo assim, se quisermos executar a rota ‘listar_posts’, por exemplo, a partir de um template localizado em outra app, definimos a tag url da seguinte forma:

<li class="nav-item">
    <a class="nav-link" href="{% url 'admin_blog:listar_posts' %}">Admin</a>
</li>

Com isso, a rota a ser executada será do método listar_posts que está definido na outra app do projeto.

O que é Flask?

Escrito em Python e disponível sobre a licença BSD (Licença de código aberto), o Flask é um micro-framework multiplataforma que provê um modelo simples para o desenvolvimento web.

Flask - Fundamentos
Curso de Flask - Fundamentos
CONHEÇA O CURSO

Mas afinal, o que é um Micro-framework?

Já falamos aqui no blog o que é um micro-framework, mas para relembrar:

Um Micro-Framework são Frameworks modularizados que possuem uma estrutura inicial muito mais simples quando comparado a um Framework convencional.

Podemos dizer que o micro-framework é uma versão minimalista destes frameworks, sendo bastante utilizado para criação de microsserviços, como APIs RESTful.

No artigo anterior, fizemos uma comparação de objetos do mundo real para exemplificar o funcionamento de um micro-framework:

Pense em um Micro-Framework como uma peça de lego. Inicialmente, um projeto criado com o micro-framework possui apenas o básico para funcionar, (normalmente, sistema de rotas), porém, ao decorrer do projeto, podem haver necessidades para utilização de outros recursos como, conexão de banco de dados, sistemas de templates, envio de email, etc. A partir desta necessidade, novas bibliotecas são “encaixadas” no projeto, como uma estrutura de lego.

De volta ao Flask…

Lançado em 2010 e desenvolvido por Armin Ronacher, o Flask é um micro-framework destinado principalmente a pequenas aplicações com requisitos mais simples, como por exemplo, a criação de um site básico.

Possui um núcleo simples e expansível que permite que um projeto possua apenas os recursos necessários para sua execução (conforme surja a necessidade, um novo pacote pode ser adicionado para incrementar as funcionalidades da aplicação).

Características do Flask

  • Simplicidade: Por possuir apenas o necessário para o desenvolvimento de uma aplicação, um projeto escrito com Flask é mais simples se comparado aos frameworks maiores, já que a quantidade de arquivos é muito menor e sua arquitetura é muito mais simples.

  • Rapidez no desenvolvimento: Com o Flask, o desenvolvedor se preocupa em apenas desenvolver o necessário para um projeto, sem a necessidade de realizar configurações que muitas vezes não são utilizadas.

  • Projetos menores: Por possuir uma arquitetura muito simples (um único arquivo inicial) os projetos escritos em Flask tendem a ser menores e mais leves se comparados a frameworks maiores.

  • Aplicações robustas: Apesar de ser um micro-framework, o Flask permite a criação de aplicações robustas, já que é totalmente personalizável, permitindo, caso necessário, a criação de uma arquitetura mais definida.

Exemplo de uma aplicação Flask

Abaixo podemos ver um exemplo de uma aplicação em Flask. Podemos notar o quão simples criar uma aplicação web pode ser:

from flask import Flask
app = Flask(__name__)

@app.route("/")
def index():
    return 'Bem-vindo a TreinaWeb!'

if __name__ == "__main__":
    app.run()

Podemos concluir que…

O Flask é uma excelente alternativa para o desenvolvimento de aplicações utilizando o Python. Ele é o principal concorrente do Django, apesar de ser considerado um micro-framework.

Aqui no blog da TreinaWeb fizemos um comparativo entre o Django e o Flask, caso esteja em dúvida em qual framework utilizar, vale a pena a leitura.

Criando o primeiro projeto Django

No artigo anterior vimos como configurar nosso ambiente de desenvolvimento para a criação de projetos Python e Django. Agora, com o ambiente devidamente configurado, veremos como criar o primeiro projeto Django utilizando as ferramentas instaladas 🙂

Criando projeto

O primeiro passo para criarmos nosso projeto com Django é abrir o PyCharm. Ao fazer isso, veremos a seguinte tela:


Dentre as três opções disponíveis, selecionaremos a “Create New Project” para criar o primeiro projeto do PyCharm. Ao fazer isso, seremos redirecionados para a seguinte tela:


Aqui, definimos a localização do projeto e onde será armazenada a virtualenv do mesmo. Se você não sabe o que é uma virtualenv, recomendo a leitura deste artigo.

Costumo armazenar a virtualenv de cada projeto em seu próprio diretório. Assim, cada projeto possuirá sua virtualenv isolada 🙂

Django - Fundamentos
Curso de Django - Fundamentos
CONHEÇA O CURSO

Depois de informar a localização do projeto e criar a virtualenv, podemos clicar em “Create” para que o PyCharm crie o diretório do projeto. No fim do processo, será exibida a seguinte tela:

Instalando o Django

Com o projeto do PyCharm criado, o primeiro passo é instalar o Django em nossa virtualenv. Para isso, o PyCharm possui uma interface gráfica que auxilia todo este processo, localizada em File > Settings > Project Interpreter (se você está utilizando o Windows ou Linux) ou PyCharm > Preferences (se você está utilizando o macOS).



É nesta janela que poderemos adicionar os pacotes à nossa virtualenv. Para isso, clicamos no botão “+” localizado no canto inferior esquerdo da janela, que exibirá uma tela para buscarmos pelo pacote desejado:


Nesta janela, buscamos pelo pacote “Django” e clicamos em “Install Package”. Após isso, o PyCharm (utilizando o PIP) vai baixar o pacote selecionado e instalar na virtualenv do projeto. Ao finalizar este processo, podemos fechar a janela e notaremos que o pacote foi instalado com sucesso:


Agora, voltando ao PyCharm, precisamos criar o projeto utilizando o Django. Para isso, no terminal integrado da IDE, digitamos o seguinte comando:

django-admin startproject primeiro_projeto

O comando acima irá criar um projeto Django chamado “primeiro_projeto” com a seguinte estrutura de pastas:


Basicamente, há quatro arquivos no projeto criado, onde a função de cada um deles pode ser vista abaixo:

  • settings.py: Arquivo para armazenar as configurações gerais do projeto, como os pacotes a serem utilizados, configurações de bancos de dados, localização de arquivos estáticos, etc.
  • urls.py: Arquivo para armazenar as rotas que serão utilizadas no projeto. Este arquivo armazenará as rotas do projeto em geral, é recomendável que cada aplicação do projeto possua um arquivo de rotas específico… Mas não se preocupe, falaremos sobre apps no próximo artigo 🙂
  • wsgi.py: Interface simples e universal para troca de informações entre servidores web e aplicações criadas com Python.
  • manage.py: Arquivo responsável por gerenciar o projeto como um todo. É, basicamente, um CLI para projetos Django.

Executando servidor Django

Com o projeto criado, podemos executar seu servidor de desenvolvimento para verificar se tudo está conforme planejado. Para isso, ainda no terminal do PyCharm, utilizamos o seguinte comando:

python manage.py runserver

Ao executar o comando acima, o servidor do Django será inicializado e poderemos acessá-lo através da rota http://127.0.0.1:8000, conforme é retornado no terminal:


Ao executar a rota citada acima em um navegador, teremos a seguinte página como resposta:


Esta (linda) página indica que a instalação foi feita corretamente e que estamos prontos para desenvolver nossa primeira aplicação com o Django o/

Ficou animado? Então fica ligado que no próximo artigo veremos como criar uma aplicação com o Django e iniciarmos seu desenvolvimento 😀

Até lá!!

Configurando ambiente de desenvolvimento para projetos Django

O Django é um ótimo framework para o desenvolvimento de aplicações com um grande reaproveitamento de código e facilidade de aprendizado. Segundo o Stack Overflow Trends, o Django é, atualmente, um dos principais frameworks full stack do mercado, sendo mais pesquisado que o Laravel e Spring. Pensando nisso, veremos neste artigo como dar nossos primeiros passos com o Django e criar nosso primeiro projeto.

O que é o Django?

Já falamos em outro artigo o que é e como funciona o Django. Basicamente, ele é um framework escrito em Python para desenvolvimento de aplicações web muito popular e com uma comunidade incrível. Não vamos entrar em detalhes mais específicos sobre o funcionamento básico do Django, já que isto pode ser visto em um artigo que já escrevemos, caso você tenha alguma dúvida, é extremamente recomendado que o leia antes de iniciar seus estudos com o framework 🙂

Django - Fundamentos
Curso de Django - Fundamentos
CONHEÇA O CURSO

Ambiente de desenvolvimento

Basicamente, o Django precisa apenas do Python instalado na máquina para que consigamos criar e executar um projeto. Porém, há três outras ferramentas que você deve considerar em seu ambiente de desenvolvimento, como veremos a seguir.

Sendo assim, o primeiro passo é instalar o Python em nossa máquina. Por ser multi-plataforma, o Python funcionará em qualquer sistema operacional que você utilizar (Windows, Linux ou macOS). Seu download pode ser feito na página oficial da ferramenta. Caso você utilize o Linux ou macOS, você já deve possuir o Python instalado em seu computador. Para verificar esta existência, podemos abrir o terminal e ditarmos o seguinte comando:

python --version

Ao executarmos o comando acima, teremos o seguinte retorno:


Lembrando que podem haver duas versões do Python instalados em sua máquina, então você pode especificar a versão que você deseja verificar a instalação (Python 2 ou Python 3).

No Windows, a instalação é simples (next > next > next > finish), tendo apenas que se atentar em marcar a opção de adicionar o Python ao PATH do sistema:

Feito isso, o Python será instalado e configurado automaticamente no Windows.

PIP, PyCharm e Virtualenv

Com o Python instalado, podemos falar das outras três ferramentas que considero essenciais para o desenvolvimento de aplicações Django: o PIP, PyCharm e Virtualenv.

O PIP é, basicamente, um gerenciador de pacotes para projetos Python. Muito utilizado quando precisamos instalar pacotes externos em nossos projetos. Já temos um ótimo artigo sobre como funciona e como instalar o PIP em nosso ambiente. Recomendo, fortemente, a leitura 🙂

Já o PyCharm é a principal IDE para desenvolvimento de aplicações Python do mercado. Desenvolvido pela Jetbrains, o PyCharm é multi-plataforma e possui as versões Professional e Community.


A instalação do PyCharm segue o velho padrão (next > next > finish) e, com certeza, você vai se encantar com todos os recursos dessa IDE no desenvolvimento de suas aplicações.

A última ferramenta é a virtualenv. Um problema muito comum é quando precisamos utilizar diversas versões de uma mesma biblioteca em diferentes projetos Python. Isso pode acarretar em conflitos entre as versões e muita dor de cabeça para o desenvolvedor. Para resolver este problema, o mais correto é a criação de um ambiente virtual para cada projeto.

Para criar estes ambientes virtuais, podemos utilizar uma virtualenv. Também possuímos aqui no blog um artigo sobre como funciona uma virtualenv no Python e como instalá-la em nossa máquina.

Ambiente configurado, e agora?

Com todas as ferramentas instaladas no computador, já estamos aptos a desenvolver primeiros projetos com o Django. Para isso, veremos no próximo artigo como criar o primeiro projeto com Django e qual a funcionalidade de cada arquivo existente em sua arquitetura 🙂

Até lá!!

Utilizando Choices no Django ORM

Na construção de um formulário, há casos em que precisamos de um campo para armazenar determinadas opções para um atributo. Um exemplo claro deste caso é o armazenamento do sexo de um usuário, que só deve permitir uma determinada lista de opções (masculino, feminino, outro).
Para estes casos, o Django ORM permite que criemos uma lista com as possíveis opções que deverão ser selecionadas, evitando que o usuário possa digitar qualquer valor naquele campo.
Sendo assim, neste artigo veremos como trabalhar com choices no Django ORM.

Criando choices no models.py

Para criar uma lista de possíveis opções no Django ORM, precisamos definir quais serão estas opções e a qual chave ela pertence. Por exemplo, se quisermos criar uma lista de opções para o campo sexo, determinamos o seguinte conteúdo no arquivo models.py do nosso projeto:

class Cliente(models.Model):
    SEXO_CHOICES = (
        ("F", "Feminino"),
        ("M", "Masculino"),
        ("N", "Nenhuma das opções")
    )

    nome = models.CharField(max_length=100, null=False, blank=False)
    sexo = models.CharField(max_length=1, choices=SEXO_CHOICES, blank=False, null=False)
    data_nascimento = models.DateField(null=False, blank=False)
    email = models.EmailField(null=False, blank=False)


    def __str__(self):
        return self.nome
Django - Banco de dados com Django ORM - Parte 1
Curso de Django - Banco de dados com Django ORM - Parte 1
CONHEÇA O CURSO

Note que precisamos criar a variável SEXO_CHOICES e determinar quais as opções que um sexo poderá exercer. Depois disso, criamos o campo sexo em nosso model e determinamos que as opções disponíveis para este campo estão definidas na variável SEXO_CHOICES. Com isso, sempre que o formulário para cadastro (ou edição) de um cliente for submetido, o Django irá verificar se uma das opções foi selecionada. Caso positivo, libera a requisição, caso negativo, alerta ao usuário que apenas estas opções são permitidas a serem selecionadas.

Um outro ponto positivo para o uso do choices é que só precisamos armazenar a chave que irá identificar cada sexo, assim, economizamos um certo espaço no banco de dados, já que só será necessário armazenar um caractere (F, M ou N), não o nome do sexo (Feminino, Masculino ou Nenhuma das opções).

Personalizando a chave primária no Django ORM

Por padrão, o ORM do Django cria, para cada tabela, um campo chamado id e é ele quem identifica, unicamente, os registros no banco de dados. Porém, muitas vezes, precisamos que este campo possua outro nome (ou até outro tipo)… E é isso que veremos neste artigo.

Django - Banco de dados com Django ORM - Parte 1
Curso de Django - Banco de dados com Django ORM - Parte 1
CONHEÇA O CURSO

Alterando nome e tipo da chave primária no Django ORM

Como exemplo para este artigo, vamos utilizar um model simples, com apenas alguns campos, conforme podemos ver abaixo:

class Pessoa(models.Model):
    nome = models.CharField(max_length=40, null=False, blank=False)
    email = models.EmailField(null=False, blank=False)

    def __str__(self):
        return self.nome

Ao realizar a migração, a seguinte estrutura será criada no banco de dados:

Podemos notar que, apesar de não definir nenhum campo com o nome id, o Django o criou automaticamente. Por padrão, este campo é do tipo int(11), não permite dados nulos e é utilizado para armazenar a chave primária da tabela. Porém, caso necessário, podemos alterar a estrutura deste campo facilmente utilizando o Django.

Para isso, a única coisa que precisamos fazer é criar um campo que será utilizado como primary_key no model do nosso projeto, como podemos ver abaixo:

class Pessoa(models.Model):
    id_personalizado = models.CharField(max_length=20, primary_key=True)
    nome = models.CharField(max_length=40, null=False, blank=False)
    email = models.EmailField(null=False, blank=False)

    def __str__(self):
        return self.nome

Sendo assim, podemos notar que a única coisa necessária para alterar a chave primária de uma tabela é determinar o atributo primary_key=True e, com isso, este campo será utilizado como chave primária no banco de dados:

Concluindo

Apesar de possuir diversas configurações padrões, o ORM do Django permite a personalização de várias delas. Neste artigo vimos o quão simples é alterar o nome da chave primária de um determinado model.

Implementando autenticação no Django – Parte 2

Continuando a implementação do módulo de autenticação em uma aplicação Django que iniciamos no artigo “Implementando autenticação no Django – Parte 1“, veremos neste artigo como implementar os métodos de logout, alterar senha do usuário e proteger páginas para que só sejam acessadas por usuários devidamente autenticados.

Logout

A principal função do método de logout é remover a sessão do usuário que está logado na aplicação, fazendo com que este login não esteja mais ativo no sistema. Assim como o método de login, o Django possui, em seu módulo de autenticação, o método para deslogar usuários. Para implementá-lo, basta criar um método no arquivo views.py com o seguinte conteúdo:

def deslogar_usuario(request):
    logout(request)
    return redirect('index')

Basicamente, o médoto deslogar_usuario recebe uma requisição e remove o usuário que está logado dela. Simplesmente assim 🙂

Agora, para acessar o método de deslogar_usuario, precisamos criar sua rota no arquivo urls.py da aplicação:

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

urlpatterns = [
    path('logar_usuario', logar_usuario, name="logar_usuario"),
    path('deslogar_usuario', deslogar_usuario, name="deslogar_usuario"),
    path('cadastrar_usuario', cadastrar_usuario, name="cadastrar_usuario"),
    path('index', index, name="index"),
]

Com isso, ao acessar a rota http://localhost:8000/deslogar_usuario, a sessão será destruída e o usuário deslogado do nosso projeto.

Alterar senha do usuário

Uma outra funcionalidade importante para um sistema de autenticação é o método para alterar senha do usuário logado. Com o Django, esta implementação é bem simples.

Primeiro, vamos criar um método alterar_senha no arquivo views.py do projeto com o seguinte conteúdo:

def alterar_senha(request):
    if request.method == "POST":
        form_senha = PasswordChangeForm(request.user, request.POST)
        if form_senha.is_valid():
            user = form_senha.save()
            update_session_auth_hash(request, user)
            return redirect('index')
    else:
        form_senha = PasswordChangeForm(request.user)
    return render(request, 'alterar_senha.html', {'form_senha': form_senha})

Basicamente, este método irá criar um PasswordChangeForm vazio para que o usuário que estiver logado digite as informações necessárias para alteração de senha (senha antiga, nova senha e confirmação da nova senha). Depois que o usuário submeter o formulário, verificamos se ele é válido e, caso positivo, alteramos a senha do usuário com o método update_session_auth_hash e redirecionamos para a página index da aplicação.

Para que o usuário consiga digitar as informações necessárias para alterar sua senha, criaremos um template chamado alterar_senha no diretório templates da nossa aplicação. Ele é bem simples, apenas renderizamos os inputs necessários para esta funcionalidade:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Alterar senha</title>
</head>
<body>

<form method="post">
    {% csrf_token %}

    <div class="form-group">
        {{form_senha.old_password.errors}}
        <label>Senha antiga: </label>
        {{form_senha.old_password}}
    </div>

    <div class="form-group">
        {{form_senha.new_password1.errors}}
        <label>Nova senha: </label>
        {{form_senha.new_password1}}
    </div>

    <div class="form-group">
        {{form_senha.new_password2.errors}}
        <label>Confirmação de senha: </label>
        {{form_senha.new_password2}}
    </div>

    <div class="form-group">
        <input type="submit" value="Alterar" class="btn btn-primary">
    </div>
</form>

</body>
</html>

Por fim, precisamos criar a rota responsável por executar o método alterar_senha. Para isso, no arquivo urls.py da aplicação, adicionamos a seguinte linha no array urlpatterns:

    path('alterar_senha/', alterar_senha, name='alterar_senha'),

Com isso, ao acessar a rota http://localhost:8000/alterar_senha, veremos o seguinte resultado:

É por meio desta página que o usuário poderá alterar sua senha na aplicação.

Proteger páginas

Sabemos que a principal vantagem de implementar a autenticação em nossas aplicações é a de proteger páginas e recursos para que apenas usuários devidamente autenticados possam acessá-las. Para isso, só precisamos adicionar o decorator login_required nos métodos que queremos proteger:

@login_required(login_url='/logar_usuario')
def index(request):
    return render(request, 'index.html')

@login_required(login_url='/logar_usuario')
def deslogar_usuario(request):
    logout(request)
    return redirect('index')

@login_required(login_url='/logar_usuario')
def alterar_senha(request):
    if request.method == "POST":
        form_senha = PasswordChangeForm(request.user, request.POST)
        if form_senha.is_valid():
            user = form_senha.save()
            update_session_auth_hash(request, user)
            return redirect('index')
    else:
        form_senha = PasswordChangeForm(request.user)
    return render(request, 'alterar_senha.html', {'form_senha': form_senha})

Agora, ao tentar acessar as páginas para alterar senha, deslogar usuário e index, o Django irá verificar se existe algum usuário logado e, caso contrário, redirecionará para a página de login.

Conclusão

Nesta série de artigo, vimos o quão fácil é implementar os principais recursos de autenticação com o Django. A autenticação é a melhor forma de garantir que os recursos de um projeto só sejam acessados por usuário previamente cadastrados e autenticados, garantindo uma maior segurança do projeto.

Lembrando que o código-fonte deste projeto se encontra neste repositório

Implementando autenticação no Django – Parte 1

A autenticação é uma das principais funcionalidades em um sistema. É com ela que protegemos as funcionalidades de uma aplicação e permitimos que estas só sejam acessadas por usuários cadastrados e autenticados previamente.

O Django possui um módulo de autenticação extremamente completo e fácil de implementar, como veremos neste artigo.

Para a construção deste projeto, vamos iniciá-lo apenas com uma página index que exibirá uma mensagem “Página protegida”. É ela quem vamos restringir para que apenas usuários autenticados possuam acesso.

Lembrando que este projeto está neste repositório.

Cadastrando usuários

Para autenticar os usuários, primeiro precisamos cadastrá-los no banco de dados. O Django possui, em seu módulo de segurança, toda uma base para este cadastro. Para utilizá-la, vamos até o arquivo views.py da nossa aplicação e criamos o seguinte método:

def cadastrar_usuario(request):
    if request.method == "POST":
        form_usuario = UserCreationForm(request.POST)
        if form_usuario.is_valid():
            form_usuario.save()
            return redirect('index')
    else:
        form_usuario = UserCreationForm()
    return render(request, 'cadastro.html', {'form_usuario': form_usuario})

O método acima é bem simples. Basicamente, ele cria uma instância do UserCreationForm passando todos os dados da requisição (dados do usuário a ser cadastrado no BD), verifica se estes dados são válidos e os persiste no banco de dados.

Lembrando que o UserCreationForm é um Form do próprio Django utilizado para cadastrar usuários no projeto.

Para que os dados sejam cadastrados, precisamos de um template para interagir com o usuário da aplicação. Sendo assim, o arquivo cadastro.html foi criado com o seguinte conteúdo:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Cadastro de usuários</title>
</head>
<body>

<form method="post">
    {% csrf_token %}

    <div class="form-group">
        {{form_usuario.username.errors}}
        <label>Username: </label>
        {{form_usuario.username}}
    </div>

    <div class="form-group">
        {{form_usuario.password1.errors}}
        <label>Senha: </label>
        {{form_usuario.password1}}
    </div>

    <div class="form-group">
        {{form_usuario.password2.errors}}
        <label>Confirmação de senha: </label>
        {{form_usuario.password2}}
    </div>

    <div class="form-group">
        <input type="submit" value="Cadastrar" class="btn btn-primary">
    </div>
</form>

</body>
</html>

O template possui apenas um formulário com os dados que um usuário deve possuir para salvá-lo no banco de dados do projeto (username e password).

Além disso, precisamos definir uma rota para o usuário conseguir acessar o formulário. Para isso, no arquivo urls.py, definimos o seguinte conteúdo:

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

urlpatterns = [
    path('cadastrar_usuario', cadastrar_usuario, name="cadastrar_usuario"),
    path('index', index, name="index"),
]

Agora, ao acessar a rota /cadastrar_usuario, o seguinte formulário será renderizado:

Ao preencher o formulário e submetê-lo, um novo usuário será criado no banco de dados do projeto, mais especificamente na tabela auth_user:

Podemos notar que o usuário foi salvo com sucesso e que sua senha foi criptografada utilizando o sha256. Além disso, o usuário joao12 ainda não se autenticou na aplicação (o que vamos fazer no próximo tópico) e que há algumas informações em branco (first_name e email), já que estas não são obrigatórias no projeto.

Agora, precisamos utilizar estas informações no banco de dados e autenticar os usuários em nossa aplicação.

Autenticando usuários

Após cadastrar os usuários no banco de dados do projeto, vamos utilizar estas informações para autenticá-los. Para isso, o primeiro passo é criar o template (login.html) onde o próprio usuário poderá preencher com seus dados de login:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form method="post">
    {% csrf_token %}

    <div class="form-group">
        {{form_login.username.errors}}
        <label>Username: </label>
        {{form_login.username}}
    </div>

    <div class="form-group">
        {{form_login.password.errors}}
        <label>Senha: </label>
        {{form_login.password}}
    </div>

    <div class="form-group">
        <input type="submit" value="Enviar" class="btn btn-primary">
    </div>
</form>
</body>
</html>

O formulário de login é bem simples. Precisamos apenas dos campos username e password para autenticar um usuário no banco de dados. De posse dessas informações, enviamos a requisição para o método logar_usuario do arquivo views.py do projeto, que capturará estes dados e logará o usuário na aplicação (caso os dados estejam corretos):

def logar_usuario(request):
    if request.method == "POST":
        username = request.POST["username"]
        password = request.POST["password"]
        usuario = authenticate(request, username=username, password=password)
        if usuario is not None:
            login(request, usuario)
            return redirect('index')
        else:
            form_login = AuthenticationForm()
    else:
        form_login = AuthenticationForm()
    return render(request, 'login.html', {'form_login': form_login})

O método logar_usuario é bem simples. Ele irá capturar os dados enviados por meio do formulário e os utilizará para autenticar um novo usuário por meio do método authenticate do Django.

Este método irá verificar se os dados de login estão corretos (de acordo com os dados presentes no banco de dados) e salvar a resposta na variável usuario. Há dois retornos possíveis para o método authenticate: None, se os dados informados estiverem incorretos, e o usuário, caso os dados estejam corretos.

Verificamos este retorno e, caso o usuário exista no banco de dados, utilizamos o método login para logá-lo na aplicação. A partir daí, este usuário estará autenticado no projeto 🙂

Lembrando que precisamos criar a rota responsável por executar o método logar_usuario no arquivo views.py:

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

urlpatterns = [
    path('logar_usuario', logar_usuario, name="logar_usuario"),
    path('cadastrar_usuario', cadastrar_usuario, name="cadastrar_usuario"),
    path('index', index, name="index"),
]

Agora, ao acessar a rota localhost:8000/logar_usuario, o formulário de login será exibido para que possamos informar as credenciais do usuário e autenticá-lo na aplicação:

Notem que o campo last_login foi preenchido com a data e hora do último login do usuário (o id do usuário mudou porque tinha esquecido sua senha, então tive que recriá-lo 😛 )

Com isso, já estamos com os métodos de login e cadastro de usuários prontos e funcionais. O próximo passo é incrementar nosso módulo de autenticação, adicionando os métodos de logout, alterar senha e proteger páginas para que apenas usuários logados possuam acesso, mas isso nós vamos fazer nos próximos artigos desta série de autenticação com Django. Até lá 🙂