Django

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

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.

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á 🙂

Principais comandos do Django CLI

Quando estamos iniciando os estudos com o Django, é bem comum esquecermos os principais comandos para gerenciar nossa aplicação (executar o servidor de desenvolvimento, criar um projeto, criar uma aplicação, criar migrações, etc). Pensando nisso, neste artigo veremos quais são os comandos responsáveis por cada uma das principais funcionalidades do CLI do Django.

Criar Projeto

Para criar um projeto no Django, utilizamos o seguinte comando no terminal:

django-admin startproject nome_do_projeto

Este comando irá criar um projeto Django vazio, com a estrutura de arquivos e diretórios padrão do framework.

Criar Aplicação

Após criar um projeto, precisamos criar uma (ou mais) aplicações para o projeto. Para isso, utilizamos o seguinte comando:

python manage.py startapp nome_da_app

Lembrando que este comando deverá ser executado no mesmo diretório em que se encontra o arquivo manage.py do projeto, ou seja, dentro do diretório padrão do projeto que estamos criando.

Criar Migrações

Após determinar quais serão as entidades que utilizaremos em nosso projeto, precisamos criar as tabelas que representam estas entidades no banco de dados. Para isso, utilizamos o seguinte comando:

python mananage.py makemigrations

O comando acima irá obter a estrutura das classes definidas no arquivo models.py e criará os arquivos de migração de cada classe.

Executar Migrações

Após criar os arquivos que definem a estrutura de cada entidade no banco de dados, precisamos executar estas migrações. Para isso, utilizamos o seguinte comando:

python manage.py migrate

Com isso, todas as classes definidas no arquivo models.py serão transformadas em tabelas no banco de dados.

Executar Servidor de Desenvolvimento

Para executar o servidor de desenvolvimento do Django e, assim, testar nosso projeto, utilizamos o seguinte comando:

python manage.py runserver

Este comando irá executar o servidor do Django no endereço http://localhost:8000, que poderá ser utilizado para executar o projeto, como podemos ver na imagem abaixo:

Limpar Banco de Dados

Quando estamos desenvolvendo nossa aplicação, é comum que queiramos limpar todos os dados do banco de dados para realizar novos testes. Para realizar este procedimento, utilizamos o seguinte comando:

python manage.py flush

Este comando irá limpar todos os dados salvos no banco de dados do projeto, mantendo sua estrutura.

Abrir Shell do Banco de Dados Configurado

Se quisermos manipular o banco de dados diretamente do shell do SGBD, podemos utilizar o seguinte comando para criar uma conexão com o mesmo:

python manage.py dbshell

Este comando irá iniciar o shell do banco de dados ao qual o projeto django está configurado, como podemos ver abaixo:

Mapear BD existente para o projeto Django

Caso você possua um banco de dados já existente e queira mapeá-lo para seu projeto Django, o seguinte comando resolve esta necessidade:

python manage.py inspectdb > nome_da_app.models.py

Este comando irá mapear o banco de dados já existente no arquivo models.py da sua aplicação, conforme vimos neste artigo.

Utilizando o Redis como Cache em um projeto Django

A performance de um projeto é de vital importância para o sucesso de uma aplicação. Dificilmente um site que demore um tempo considerável para responder uma solicitação de um usuário, não sucumbirá ao fracasso. Pensando nisso, há diversas maneiras de tentar melhorar o desempenho de uma aplicação, dentre elas, utilizar o Cache para armazenar dados que são frequentemente utilizados, é uma ótima alternativa.

Como funciona o Cache

O Cache é um recurso que possibilita o acesso às informações de forma mais rápida. Basicamente, é uma forma de armazenar determinadas informações que são consumidas com mais frequência para que elas sejam disponibilizadas no menor tempo possível.

O funcionamento do Cache pode ser entendido da seguinte forma:

  1. A aplicação verifica se os dados solicitados estão em cache;

  2. Se sim, o cache devolve para a aplicação, que os exibe;

  3. Se não, os dados são obtidos do banco de dados, salvos no cache e retornados para aplicação;

  4. Da próxima vez, o cache já possuirá os dados armazenados e, assim, retornados em um tempo menor.

Instalando o Redis

A instalação do Redis varia conforme o sistema operacional utilizado, abaixo veremos como instalar o Redis no Windows, Linux e macOS.

Windows

A instalação do Redis no Windows é bem simples. Primeiro, precisamos baixar o arquivo .zip do diretório oficial do Redis ():

Após realizar o download, descompactamos e executamos o arquivo redis-server, localizado no diretório 32bits ou 64bits, dependendo do sistema operacional.

Linux

A instalação do Redis no Linux também é bem simples. Primeiro, abrimos o terminal e digitamos os seguintes comandos:

sudo apt-get install redis-server
sudo systemctl enable redis-server.service

Com isso, o Redis será instalado e executado no Linux.

macOS

Para instalar o Redis no macOS também é super simples. Com o Homebrew instalado, podemos abrir o terminal e digitar o seguinte comando:

brew install redis
ln -sfv /usr/local/opt/redis/*.plist ~/Library/LaunchAgents

Com isso, o Redis será instalado e configurado para iniciar sempre que ligarmos o computador.

Configurando o Redis no Django

Com o Redis instalado, precisamos configurar a comunicação entre as tecnologias (Django e Redis). Para isso, o primeiro passo é instalar o pacote django-redis na virtualenv do projeto seguindo os seguintes passos:

No PyCharm, vamos até a aba “Project Interpreter” e clicamos no “+” localizado no canto inferior esquerdo:

Após isso, buscamos pelo pacote “django-redis” e o instalamos em nossa virtualenv:


Com isso, o Redis já está pronto para ser utilizado em nosso projeto Django 🙂

Utilizando o Redis como Cache

Após instalar e configurar o Redis em nosso projeto Django, precisamos configurar o projeto para utilizar o Redis como Cache das informações. Para isso, no arquivo settings.py, adicionamos a seguinte configuração:

CACHES = {
    'default': {
        'BACKEND': 'django_redis.cache.RedisCache',
        'LOCATION': 'redis://127.0.0.1:6379/1',
        'OPTIONS': {
            'CLIENT_CLASS': 'django_redis.client.DefaultClient'
        },
        'KEY_PREFIX': 'django_orm'
    }
}

A configuração acima permitirá que o Django se comunique com o servidor do Redis que está sendo executado localmente.

Agora precisamos indicar quais páginas utilizarão o Cache para armazenar suas informações. Para isso, no nosso arquivo de views do projeto, adicionamos a anotação @cache_page(tempo_de_vida_cache) nos métodos que queremos utilizar o cache (normalmente, nas páginas com mais acessos):

@cache_page(60)
def listar_clientes(request):
    clientes = cliente_service.listar_clientes()
    return render(request, 'clientes/lista_clientes.html', {'clientes': clientes})

Com isso, sempre que um usuário solicitar o método para listagem de todos os clientes, o Django, primeiro, verificará se estas informações existem no Redis. Se sim, é de lá que as informações serão listadas, caso contrário, o Django fará uma consulta no banco de dados, obterá a lista de clientes, inserirá no cache e retornará ao usuário.

Comparando performances

A quantidade de requisições por segundo pode variar um pouco, mas é bem nítido o ganho de performance do uso do Redis como Cache em nossa aplicação. Na imagem abaixo podemos ver a diferença entre a quantidade de requisições utilizando o Redis e o uso do banco de dados:

Conclusão

O uso do Cache é uma ótima alternativa quando precisamos garantir o retorno dos dados em um tempo menor em páginas que são frequentemente acessadas. Vale lembrar que não devemos (e nem precisamos) usá-lo em todas as páginas, apenas nas mais acessadas.

Mapeando banco de dados existente com Django

O Django é um ótimo framework para iniciar um projeto completamente do zero, mas nem sempre este é nosso caso. Imagine que uma empresa pretende migrar uma aplicação legada (antiga) com 100 tabelas em seu banco de dados e escolhe o Django como sua nova tecnologia… Como faríamos para mapear todo o banco de dados (tabelas e relações) para nosso projeto? Parece algo cansativo e complicado, certo!? Bom, com o Django, isso pode ser mais fácil do que parece…

Banco de Dados

Para nosso exemplo, iremos utilizar um banco de dados com uma estrutura que armazena a lista de empregados de uma empresa e suas relações. Não vamos nos preocupar com a estrutura do banco de dados em si, o importante aqui é entender que teremos 6 tabelas com os seguintes campos:

Para criar o banco de dados acima em seu MySQL, precisamos baixar toda a sua estrutura no repositório encontrado no seguinte link:

Depois disso, vamos baixar seu código-fonte e salvar no Desktop do nosso computador. Depois de descompactado, utilizamos o terminal para incorporar o banco de dados teste para o MySQL presente em nossa máquina. Para isso, no terminal (ou CMD), utilizamos o seguinte comando:

mysql -u root -p < employees.sql

Lembrando que o “root” é o nome do usuário do banco de dados. Caso o seu seja diferente, informe-o na instrução acima 🙂

Depois disso, o banco employees será criado no MySQL:

Lembrando que o BD que utilizamos já virá populado, contendo mais de 300,000 empregados registrados. Situação parecida ao que descrevemos anteriormente:

Configurando aplicação

Após criar o banco de dados, estamos prontos para mapeá-lo em nosso projeto Django. Para isso, partiremos de uma aplicação “zerada”, apenas com o projeto e uma app criada. Além disso, precisamos instalar, obviamente, o Django e o mysqlclient em nossa virtualenv:


Além disso, precisamos configurar o projeto para se comunicar com o banco de dados que acabamos de importar. Para isso, no arquivo settings.py do nosso projeto, determinamos seus parâmetros de conexão:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'employees',
        'USER': 'root',
        'PASSWORD': 'root',
        'HOST': 'localhost',
        'PORT': '3306'
    }
}

Com isso, temos nossa aplicação criada e se comunicando com o banco de dados \o

Mapeando o banco de dados no Django

Depois de configurar a aplicação, chegou a hora tão esperada: mapear o banco de dados para nosso arquivo models.py 😀

Para isso, é muito simples (e você vai se impressionar com isso). Tudo que temos que fazer é abrir o terminal integrado do PyCharm e digitar o seguinte comando:

python manage.py inspectdb > nome_da_app.models.py

Lembrando que “nome_da_app” deve ser alterada pelo nome da sua app no projeto, hein!? 🙂

Após isso, no arquivo models.py da nossa aplicação, teremos o seguinte resultado:

from django.db import models


class Departments(models.Model):
    dept_no = models.CharField(primary_key=True, max_length=4)
    dept_name = models.CharField(unique=True, max_length=40)

    class Meta:
        managed = False
        db_table = 'departments'


class DeptEmp(models.Model):
    emp_no = models.ForeignKey('Employees', models.DO_NOTHING, db_column='emp_no', primary_key=True)
    dept_no = models.ForeignKey(Departments, models.DO_NOTHING, db_column='dept_no')
    from_date = models.DateField()
    to_date = models.DateField()

    class Meta:
        managed = False
        db_table = 'dept_emp'
        unique_together = (('emp_no', 'dept_no'),)


class DeptManager(models.Model):
    emp_no = models.ForeignKey('Employees', models.DO_NOTHING, db_column='emp_no', primary_key=True)
    dept_no = models.ForeignKey(Departments, models.DO_NOTHING, db_column='dept_no')
    from_date = models.DateField()
    to_date = models.DateField()

    class Meta:
        managed = False
        db_table = 'dept_manager'
        unique_together = (('emp_no', 'dept_no'),)


class Employees(models.Model):
    emp_no = models.IntegerField(primary_key=True)
    birth_date = models.DateField()
    first_name = models.CharField(max_length=14)
    last_name = models.CharField(max_length=16)
    gender = models.CharField(max_length=1)
    hire_date = models.DateField()

    class Meta:
        managed = False
        db_table = 'employees'


class Salaries(models.Model):
    emp_no = models.ForeignKey(Employees, models.DO_NOTHING, db_column='emp_no', primary_key=True)
    salary = models.IntegerField()
    from_date = models.DateField()
    to_date = models.DateField()

    class Meta:
        managed = False
        db_table = 'salaries'
        unique_together = (('emp_no', 'from_date'),)


class Titles(models.Model):
    emp_no = models.ForeignKey(Employees, models.DO_NOTHING, db_column='emp_no', primary_key=True)
    title = models.CharField(max_length=50)
    from_date = models.DateField()
    to_date = models.DateField(blank=True, null=True)

    class Meta:
        managed = False
        db_table = 'titles'
        unique_together = (('emp_no', 'title', 'from_date'),)

Exatamente a mesma estrutura (com seus atributos e relacionamentos) presentes no banco de dados que incorporamos ao MySQL da nossa máquina. Bem legal, né!?

Imagine ter que mapear todas essas entidades, avaliando seus tipos de dados e relações… Seria um trabalho bem cansativo, concorda? Com o Django, um simples comando consegue resolver este problema 🙂

Agora, já estamos prontos para utilizar todo o poder do ORM do Django para manipular o banco de dados e, consequentemente, criar nossa nova aplicação \o

Relacionamento 1-1, 1-N e N-N com Django

No modelo relacional, existem três tipos de associação entre entidades (tabelas) distintas. Estas relações são utilizadas para mapear como as tabelas interagem entre si e podem ser classificadas de três formas: 1-1 (um para um), 1-N (um para muitos) e N-N (muitos para muitos).

Sendo assim, veremos neste artigo como funciona e como implementar os três tipos de relacionamento no Django.

Relacionamento 1-1

Assim como o próprio nome supõe, o relacionamento 1-1 define que um item de uma entidade só poderá se relacionar com um item de outra entidade. Por exemplo, supondo que temos as entidades Cliente e Endereço que se relacionam de forma 1-1, um cliente só poderá possuir um endereço, que também só pode estar relacionado a um cliente.

Para criar este tipo de relacionamento no Django, no arquivo models.py, precisamos criar um campo que armazene o ID do endereço na entidade cliente do tipo OneToOneField:

class Endereco(models.Model):
        # Definimos seus atributos

class Cliente(models.Model):
        # Definimos seus atributos
      endereco = models.OneToOneField(Endereco, on_delete=models.SET_NULL, null=True)

Desta forma, a classe Cliente irá armazenar o ID do Endereço que cada cliente possuirá. O código completo das classes Endereço e Cliente podem ser vistas abaixo:

class Endereco(models.Model):
    rua = models.CharField(max_length=200, null=False, blank=False)
    numero = models.IntegerField(null=False, blank=False)
    complemento = models.CharField(max_length=200, null=False, blank=False)
    bairro = models.CharField(max_length=50, null=False, blank=False)
    cidade = models.CharField(max_length=100, null=False, blank=False)
    pais = models.CharField(max_length=50, null=False, blank=False)

    def __str__(self):
        return self.rua

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)
    data_nascimento = models.DateField(null=False, blank=False)
    email = models.EmailField(null=False, blank=False)
    profissao = models.CharField(max_length=50, null=False, blank=False)
    sexo = models.CharField(max_length=1, choices=SEXO_CHOICES, blank=False, null=False)
    endereco = models.OneToOneField(Endereco, on_delete=models.SET_NULL, null=True)

Após definir as classes acima, precisamos criar a migração para efetivar as alterações no banco de dados e, assim, criar as tabelas no banco de dados. Para isso, utilizamos os comandos abaixo:

python manage.py makemigrations

python manage.py migrate

Isso fará com que as tabelas sejam criadas no banco de dados com a seguinte estrutura:

Relacionamento 1N

O relacionamento 1N determina que um item de uma tabela pode se relacionar com vários itens de uma outra tabela. Continuando o exemplo acima, podemos determinar que um cliente pode realizar diversos pedidos em um restaurante, porém cada pedido só pode possuir um cliente atrelado a ele.

Para criar este relacionamento no Django, utilizamos um campo do tipo ForeignKey, como podemos ver abaixo:

class Pedido(models.Model):
    cliente = models.ForeignKey("Cliente", on_delete=models.CASCADE, related_name='pedidos')

Isso fará com que a tabela Pedidoarmazene o ID do cliente de cada relação. O código completo das classes Pedido e Cliente pode ser visto abaixo:

class Pedido(models.Model):
    STATUS_CHOICES = (
        ("P", "Pedido realizado"),
        ("F", "Fazendo"),
        ("E", "Saiu para entrega"),
    )
    cliente = models.ForeignKey("Cliente", on_delete=models.CASCADE, related_name='pedidos')
    observacoes = models.CharField(max_length=300, null=False, blank=False)
    data_pedido = models.DateTimeField(default=timezone.now)
    valor = models.FloatField(blank=False, null=False)
    status = models.CharField(max_length=1, choices=STATUS_CHOICES, blank=False, null=False)

    def __str__(self):
        return self.cliente.nome

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)
    data_nascimento = models.DateField(null=False, blank=False)
    email = models.EmailField(null=False, blank=False)
    profissao = models.CharField(max_length=50, null=False, blank=False)
    sexo = models.CharField(max_length=1, choices=SEXO_CHOICES, blank=False, null=False)
    endereco = models.OneToOneField(Endereco, on_delete=models.SET_NULL, null=True)

Após definir as classes acima, precisamos criar a migração para efetivar as alterações no banco de dados e, assim, criar as tabelas no banco de dados. Para isso, utilizamos os comandos abaixo:

python manage.py makemigrations

python manage.py migrate

Isso fará com que as tabelas sejam criadas no banco de dados com a seguinte estrutura:

Agora, a tabela Pedido armazenará, além de todos os seus atributos, o ID do cliente. Assim, um cliente poderá estar relacionado a vários pedidos, porém um pedido só pode se relacionar com um único cliente.

Relacionamento NN

O relacionamento NN define que um item de uma tabela pode se relacionar com vários itens de uma outra tabela e vice-versa. Por exemplo, podemos determinar que um pedido pode possuir diversos produtos relacionados a ele, assim como um mesmo produto pode estar relacionado a diversos pedidos diferentes.

Para criar este tipo de relacionamento, utilizamos um campo do tipo ManyToManyField, como podemos ver abaixo:

class Produto(models.Model):
    nome = models.CharField(max_length=50, null=False, blank=False)
    descricao = models.CharField(max_length=200, null=False, blank=False)
    valor = models.FloatField(null=False, blank=False)

    def __str__(self):
        return self.nome

class Pedido(models.Model):
    STATUS_CHOICES = (
        ("P", "Pedido realizado"),
        ("F", "Fazendo"),
        ("E", "Saiu para entrega"),
    )
    cliente = models.ForeignKey("Cliente", on_delete=models.CASCADE, related_name='pedidos')
    observacoes = models.CharField(max_length=300, null=False, blank=False)
    data_pedido = models.DateTimeField(default=timezone.now)
    valor = models.FloatField(blank=False, null=False)
    status = models.CharField(max_length=1, choices=STATUS_CHOICES, blank=False, null=False)
    produtos = models.ManyToManyField(Produto)

    def __str__(self):
        return self.cliente.nome

Após definir as classes acima, precisamos criar a migração para efetivar as alterações no banco de dados e, assim, criar as tabelas no banco de dados. Para isso, utilizamos os comandos abaixo:

python manage.py makemigrations

python manage.py migrate

Isso fará com que as tabelas sejam criadas no banco de dados com a seguinte estrutura:

Para este tipo de relacionamento, uma tabela “auxiliar” será criada para armazenar os IDs do pedido e do produto que se relaciona.

A tabela clientes_pedido_produtosirá armazenar o id do pedido e o id do produto que fazem relação. Desta forma, um pedido pode se relacionar com diferentes produtos e um produto pode estar relacionado a diferentes pedidos.

Conclusão

Vimos neste artigo o quão simples é criar os três tipos de relacionamento em bancos de dados relacionais utilizando o ORM do Django. Com isso, agora podemos criar nossas aplicações e estruturar nosso banco de dados da melhor forma possível.

O que é Django?

O Django é um framework gratuito e de código aberto escrito em Python para desenvolvimento web. Sua utilização permite a construção de aplicações web de alto desempenho.

O que é um Framework?

O framework é um facilitador no desenvolvimento de diversas aplicações, e sem dúvida, sua utilização poupa tempo e custos para quem utiliza, pois de forma mais básica, é um conjunto de bibliotecas utilizadas para criar uma base onde as aplicações são construídas, um otimizador de recursos. Tem como principal objetivo resolver problemas recorrentes com uma abordagem mais genérica. Ele permite ao desenvolvedor focar nos “problemas” da aplicação, não na arquitetura e configurações.

História do Django

Lançado em 2005 sob a licença BSD (de código aberto), o Django foi desenvolvido inicialmente como um sistema de gerenciamento de um site jornalístico. Tem como seus co-criadores os desenvolvedores Adrian Holovaty e Simon Willison. A escolha do nome “Django” foi inspirado no músico de jazz Django Reinhardt, considerado um dos melhores e mais influentes guitarristas de todos os tempos. \o/

Padrão MTV

O Django utiliza o padrão de projeto MTV (Model, Template e View), que é basicamente:

Model: Onde acontece toda interação com o banco de dados;

Template: Onde acontece a renderização dos dados para uma visualização mais intuitiva, em outras palavras, a interação do usuário com o site em Django;

E a View: Lógica sobre os dados. A camada responsável pelas regras de negócio do sistema Django.

Por ser popular, o Django possui uma grande comunidade de desenvolvedores. Com isso, fica muito mais fácil encontrar materiais de estudo e programadores dispostos a se ajudarem.

Utiliza o princípio Don´t Repeat Yourself ou simplesmente DRY, permitindo que as aplicações sejam desenvolvidas com a maior quantidade de aproveitamento de código possível.

Concluindo:

Com isso, vimos algumas das principais características do Django, o que o torna um framework muito utilizado e que, com certeza, você deve levar em consideração quando iniciar um projeto. =)

Utilizando arquivos estáticos em um projeto Django

A utilização de arquivos estáticos no Django necessita de algumas configurações para ser feita, como veremos neste artigo 🙂

Configurando aplicação

Com a aplicação aberta no PyCharm, precisamos configurar o diretório em que os arquivos estáticos (JS, CSS e IMG) serão armazenados. Para isso, vamos até o final do arquivo settings.py do nosso projeto até encontrar a configuração STATIC_URL, é ela quem define o diretório que os arquivos estáticos serão armazenados.

Por padrão, o Django armazena os arquivos estáticos em um diretório chamado static, localizado na aplicação. Sendo assim, é lá que vamos armazenar os arquivos CSS, JS e IMG da aplicação.

Para isso, o primeiro passo é criar um diretório chamado static na aplicação e, dentro do diretório static, criar uma outra pasta com o nome da aplicação. Por exemplo, se a aplicação possuir o nome “minha_aplicacao”, precisamos criar um diretório static/minha_aplicacao dentro da app que estamos desenvolvendo:

Note que na imagem acima, estamos criando um diretório com o mesmo nome da aplicação “app” dentro do diretório “static” e, dentro do diretório “app”, criamos as pastas para armazenar os arquivos css, js e img.

Com isso, só precisamos armazenar os arquivos estáticos do projeto em seu respectivo diretório. Como exemplo, vamos criar um arquivo css simples e armazená-lo no diretório static/app/css com o nome style.css e com o seguinte conteúdo:

body {
  background-color: lightblue;
}

h1 {
  color: navy;
  margin-left: 30px;
}

Utilizando arquivos nos templates

Agora que já configuramos a localização dos arquivos estáticos e criamos o css de exemplo, precisamos importá-lo em nossos templates. Para isso, o processo é bem simples:

1 – Carregamos a tag static do Django em nosso template (linha 2);

2 – Carregamos o arquivo css utilizando a tag (linha 7). Note que precisamos determinar o caminho, a partir do diretório static, do arquivo css que criamos anteriormente.

<!DOCTYPE html>
{% load static %}
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Página de testes</title>
    <link rel="stylesheet" href="{% static 'app/css/style.css' %}">
</head>
<body>

<h1>Olá, mundo</h1>

</body>
</html>

Testando aplicação

Agora, ao executar a aplicação e renderizar o template com o css importado, teremos o seguinte resultado:

JUNTE-SE A MAIS DE 150.000 PROGRAMADORES