👨💻 # Este repositório abriga um abrangente tutorial sobre o desenvolvimento web usando o framework Django. Aprenda passo a passo a criar um aplicativo web, desde a configuração inicial até o deploy em um ambiente de produção.
- Fase 1: Configuração Inicial e Ambiente de Desenvolvimento
- Fase 2: Estrutura de Diretórios e Primeiras Configurações
- Fase 3: Models e Banco de Dados
- Fase 4: Views e URLs
- Fase 5: Templates e Páginas HTML (static, partials, layout, media)
- Fase 6: MVT (Model-View-Template) e Integração
- Fase 7: Administração do Django
- Fase 8: Formulários e Validação
- Fase 9: Autenticação e Autorização
- Fase 10: CRUD (Create, Read, Update, Delete)
- Fase 11: Testes e Depuração
- Fase 12: Deploy (Implantação) em Produção
- 🔔 Certifique-se de que o Python e Pip estejam instalados no seu sistema. Você pode verificar isso executando o seguinte comando no seu terminal ou prompt de comando:
python --version
pip --version
Caso contrário, você pode baixa-los em seus sites e seguirem as instruções de instalação em Python e Pip
Pip (Python Package Installer) geralmente é incluído na instalação do Python mais recente.
🗃️ # Um ambiente virtual é uma prática recomendada para isolar as dependências do seu projeto. Isso garante que você possa ter várias versões do Django e de outras bibliotecas em diferentes projetos sem conflitos.
3. Execute o seguinte comando para criar o ambiente virtual (substitua nome-do-ambiente
pelo nome que você deseja para o seu ambiente):
- 🖥️ No Windows:
python -m venv nome-do-ambiente
- 💻 No macOS e Linux:
python3 -m venv nome-do-ambiente
- 🖥️ No Windows:
nome-do-ambiente\Scripts\activate
- 💻 No macOS e Linux:
source nome-do-ambiente/bin/activate
Agora, você está dentro do ambiente virtual e pode instalar as dependências específicas do projeto, incluindo o Django, quando ativar a venv seu terminal ficará assim:
- 🔩 Lembrando que quando fechar o seu editor e abrir novamente, terá de ativar a venv (ambiente virtual) novamente seguindo a etapa 1.2.4
- 🔔 Dentro do ambiente virtual, você pode instalar o Django executando o seguinte comando no terminal ou prompt de comando:
pip install django
Isso instalará a versão mais recente do Django no seu ambiente virtual.
-
🔔 Agora que o Django está instalado, você pode criar um novo projeto Django com o seguinte comando (substitua nome-do-projeto pelo nome que você deseja para o projeto):
-
📌 Recomendo que o nome seja setup, dessa forma fica mais fácil para diferenciar a pasta de setup onde serão guardadas as configurações do seu site, depois é só renomear o nome do projeto para nome-do-projeto que você desejar.
django-admin startproject nome-do-projeto
ou
django-admin startproject setup
👨👦 # Assim criará a estrutura inicial do seu projeto Django, incluindo arquivos e diretórios necessários, pode renomear o diretório "pai" do projeto sem alterar o diretório setup que estiver dentro dele, normalmente os 2 possuem o mesmo nome, por isso que haverá complicações na hora de navegar.
- 🔔 Para criar um novo aplicativo dentro do projeto, execute o seguinte comando no terminal ou prompt de comando dentro do diretório (nome-do-projeto) onde é o seu projeto (substitua nome-do-app pelo nome do aplicativo):
cd nome-do-projeto
python manage.py startapp nome-do-app
Isso criará a estrutura de diretórios e arquivos para o seu novo aplicativo Django.
📌 # O servidor de desenvolvimento é uma ferramenta que permite que você teste e visualize seu aplicativo enquanto o desenvolve. Lembre-se de que o servidor de desenvolvimento é destinado apenas para uso durante o desenvolvimento e testes.
2. Navegue até a pasta raiz do seu projeto Django, onde está localizado o arquivo manage.py
. Use o comando cd
para acessar a pasta (WebBooks
é o nome da minha pasta Raiz/Pai do projeto).
3. Agora que você está na pasta do projeto e com o ambiente virtual ativado, você pode iniciar o servidor de desenvolvimento com o seguinte comando:
- 🖥️ No Windows:
python manage.py runserver
- 💻 No macOS e Linux:
python3 manage.py runserver
4. Após executar o comando, o servidor de desenvolvimento começará a ser executado. Você verá mensagens no terminal indicando que o servidor está "exibindo" em um endereço, normalmente em http://127.0.0.1:8000/, é só clicar por cima e entrar no link e você conseguirá observar a página inicial do seu projeto:
🗂️ # Um projeto Django possui uma estrutura de diretórios organizada. Vamos dar uma olhada nos diretórios e arquivos principais, usaremos os meus exemplos como referência:
WebBooks/
: Este é o diretório raiz do seu projeto, no seu caso será o nome-do-projeto que você escolheu, além de que pode ser possível renomea-lo sem problemas-
setup/
: O diretório interno com o mesmo nome contém as configurações do projeto, caso renomea-lo terá de reconfigurar todos os arquivos internos dele.
-
-
settings.py
: Arquivo de configurações do projeto.
-
-
-
urls.py
: Arquivo de configurações de URLs.
-
-
-
wsgi.py
: Arquivo de configuração do servidor WSGI (usado para implantação em produção).
-
-
Website/
: O diretório do seu aplicativo.
-
-
__init__.py
: Um arquivo Python vazio que informa ao Python que o diretório deve ser tratado como um pacote.
-
-
-
admin.py
: Este arquivo é usado para configurar a administração do aplicativo, permitindo que você gerencie os modelos de dados por meio da interface de administração.
-
-
-
apps.py
: Arquivo de configuração do aplicativo, onde você pode definir metadados do aplicativo.
-
-
-
models.py
: Neste arquivo, você define os modelos de dados do aplicativo, que representam as tabelas do banco de dados.
-
-
-
tests.py
: Este é o local para escrever testes de unidade para o aplicativo.
-
-
-
views.py
: Neste arquivo, você define as visualizações que controlam a lógica de exibição do aplicativo.
-
-
-
migrations/
: Este diretório é criado quando você executa migrações e contém os arquivos de migração do aplicativo.
-
-
-
templates/
: Aqui, você pode criar diretórios e arquivos de modelos HTML usados para renderizar as páginas do aplicativo.
-
-
-
static/
: Diretório onde você pode armazenar arquivos estáticos, como folhas de estilo CSS, scripts JavaScript e imagens.
-
-
manage.py
: Um utilitário de linha de comando para gerenciar seu projeto.
🔩 - Algumas dessas estruturas iremos criar ao longo do tutorial
🔔 # Nesse tutorial iremos utilizar uma das formas de configurar o banco de dados, que é a utilização do XAMPP, Workbench MySQL e MySQL
- Faça o download e instale o XAMPP
- Faça o download e instale o MySQLclient (Marque a opção MySQL Client na hora da instalação)
- Faça o download e instale o MySQL Workbench (É possível instalar o Workbench apenas com a instalação da etapa acima)
- Inicie o XAMPP Control Panel e certifique-se de que o servidor Apache e o servidor MySQL estejam em execução.
- Abra o MySQL Workbench e clica no "+" para criar seu servidor.
- Crie um novo servidor MySQL se ainda não tiver um configurado e coloque o nome da "Connection Name", se quiser pode colocar uma senha em "Password" e clica em "Ok"
-
Anote o nome do banco de dados, o nome de usuário (USERNAME) e a senha (PASSWORD) que você configurou no MySQL Workbench.
-
Crie um novo esquema "schema" de banco de dados (database) para o seu projeto Django (por exemplo, 'WebBooksBD').
É importante que o "Charset/Collation" sejam utf8 e utf8_unicode_ci como na imagem, e depois dê Apply:
Depois de concordar tudo e finalizar as confirmações, seu banco será criado:
-
Abra o arquivo de configuração do banco de dados no seu projeto Django, que normalmente está localizado em
setup/settings.py
. -
Na seção INSTALLED_APPS, você vai inserir o nome do seu app entre os que já foram inseridos, colocando o 'nome-do-app', dentro da seção como no exemplo:
Caso queira confirmar qual é o nome do seu app, é só entrar no seu app e no arquivo
apps.py
, lá você encontrará esse "name", é só copiar e colar.
- Na seção DATABASES, você pode configurar a conexão com o MySQL Workbench. Substitua as configurações existentes pelas seguintes:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'WebBooksBD', # Nome do banco de dados que você criou no MySQL Workbench.
'USER': 'seu_usuario_mysql', # Nome de usuário do MySQL.
'PASSWORD': 'sua_senha_mysql', # Senha do MySQL.
'HOST': 'localhost', # Endereço do servidor do MySQL (normalmente 'localhost').
'PORT': '3306', # Porta do MySQL (normalmente '3306').
}
}
Certifique-se de substituir 'seu_usuario_mysql' e 'sua_senha_mysql' pelas credenciais reais do MySQL que você configurou no MySQL Workbench como as do meu:
🌎 # Aqui iremos instalar os pacotes necessários para o funcionamento do Banco de Dados com Django, vamos instalar os pacotes necessários na Venv
🚀 # A não ser que você deseja baixar todos esses pacotes e recursos de forma global fora da Venv, você pode sair da venv toda vez que for iniciar o Runserver.
Sair da Venv:
- Você pode estar fechando e abrindo o editor de codigo que você estiver utilizando, dessa forma a venv fechará também
- Caso dessa forma não dê certo, podemos utilizar esses comandos no terminal ou prompt de comando antes de fechar e abrir o editor.
🖥️ No Windows:
nome-do-ambiente\Scripts\deactivate💻 No macOS e Linux:
deactivatePacotes Necessários:
- Para que o Django possa se comunicar com o banco de dados MySQL, você precisa instalar pacotes Python que oferecem suporte ao MySQL. Existem duas opções comuns:
mysql-connector-python
emysqlclient
.pip install mysql-connector-pythonpip install mysqlclientExemplo sem a Venv:
🛡️ - Depois ative novamente a Venv que você desativou usando os comandos que já foram ensinados para dar continuidade as configurações do seu projeto.
🔔 # Nesta fase, você criará modelos para representar dados em seu aplicativo Django e entenderá como o Django ORM (Object-Relational Mapping) funciona para mapear esses modelos para tabelas no banco de dados.
- Modelos são classes que definem a estrutura dos dados que você deseja armazenar em seu banco de dados. Vamos criar um modelo simples como exemplo. Suponha que você esteja criando um aplicativo de gerenciamento de livros. Aqui está um exemplo de modelo de livro:
from django.db import models
class Livro(models.Model):
titulo = models.CharField(max_length=200)
autor = models.CharField(max_length=100)
publicação = models.DateField()
paginas = models.IntegerField()
🔔 - Neste exemplo, criamos um modelo de livro com campos como título, autor, data de publicação e número de páginas. Você pode personalizar os campos de acordo com suas necessidades.
- Agora que você criou o modelo, é hora de criar uma migração para aplicá-lo ao banco de dados.
1. No terminal, dentro do diretório raiz/pai do projeto, execute o seguinte comando para criar uma migração:
python manage.py makemigrations
python manage.py migrate
- O Django oferece um painel de administração prontamente disponível para gerenciar os dados do banco de dados. Vamos habilitá-lo.
from django.contrib import admin
from .models import Livro
admin.site.register(Livro)
- from .models import Livro: Retira de dentro do arquivo
models.py
a class chamadaLivro
.- admin.site.register(Livro): Indica que no painel de Administrador do Django será possível registrar dados na tabela chamada
Livro
.
-
Para acessar o painel de administração, você precisará criar um superusuário.
-
No terminal, dentro do diretório do projeto, execute o seguinte comando e siga as instruções para criar um superusuário, e depois preencha os parâmetros com nome e senha que você não esquecerá, se preferir pode usar como no exemplo:
python manage.py createsuperuser
🔩 - O Password é invisível por questões de segurança, o Email pode ser aleatório ou o seu oficial, as informações colocadas no exemplo são:
- Username: admin
- Email: [email protected]
- Password: 1234
- Password (again): 1234
- Confirmação se vou usar senha fraca: y
- Agora quando você fazer o comando do Runserver que já foi ensinado na etapa 1.6.3, vá na URL do seu navegador e adiciona
/admin
e faça o login da sua conta que você criou aqui no Django.
🎛️ # Nesse painel você consegue ter acesso para inserir informações, remover, editar e ler dados inseridos no seu banco de dados, esse ambiente não é recomendável que seja acessado por qualquer usuário, até mesmo para funcionários, é um ambiente de trabalho apenas do ADM do Banco de Dados ou usuários com privilégios elevados.
- Views são funções ou classes que processam solicitações do navegador e retornam respostas. Vamos criar uma view simples que exibe uma lista de livros.
from django.shortcuts import render
from .models import Livro
def lista_livros(request):
livros = Livro.objects.all()
return render(request, 'lista_livros.html', {'livros': livros})
Nesta view, estamos obtendo todos os objetos de livro do banco de dados e passando-os para um template chamado lista_livros.html.
- livros = Livro.objects.all(): Pega todos os
objects
de models chamadoLivro
e passa-os para dentro da variávellivros
.- render(request, 'lista_livros.html'): Ele renderizará usando o
request
, o template (site) chamadolista_livros.html
de dentro da pastatemplates
(OBS: vamos criar a pasta ainda).- {'livros' : livros}: Ele criará um dicionário chamado
livros
e pegará a variávellivros
e receber todas as informações guardadas dentro da variável.
🔔 # As URLs mapeiam solicitações para views. Vamos definir uma URL que chama a view
lista_livros
.
from django.urls import path
from . import views
urlpatterns = [
path('livros/', views.lista_livros, name='lista_livros'),
]
Agora, quando os usuários acessarem
/livros/
em seu site, a view lista_livros será chamada.
- from . import views: Importa da pasta atual (Website) tudo do arquivo views.py (Class, Funções, Métodos, etc.)
- path('livros/', views.lista_livros, name='lista_livros'): Para acessar a
views.lista_livros
é necessário que o usuário esteja na página da URLlivros/
, o nome dessa path é nomeada delista_livros
📌 OBS: A colocação de "," dentro do
urlpatterns
permite que possa ser criada váriaspath
de uma vez, então é possível a criação de várias views e URLs para essas views em seu aplicativo.
🔔 # Para que o setup do seu projeto reconheça que as configurações feitas nas URLs de dentro do seu aplicativo (Website) são oficiais, é necessário interligar uma ponte de acesso entre eles utilizando o
include
- Navegue até o setup do seu diretório Raiz/Pai, procure pelo arquivo chamado
urls.py
e faça as devidas interligações:
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('Website.urls'))
]
- Como no exemplo:
- path('', include('Website.urls')): Ele faz um path dizendo que naturalmente todas as urls do aplicativo chamado
Website
localizados dentro do arquivourls
sejam acrescentadas/incluidas.
🔔 # Um template é um arquivo HTML que define como os dados são apresentados. Vamos criar um template para exibir a lista de livros.
1. Crie uma pasta chamada templates
no diretório do seu aplicativo (por exemplo, Website/templates
).
2. Dentro da pasta templates, crie um arquivo chamado lista_livros.html
(por exemplo, Website/templates/lista_livros.html
)
3. No arquivo lista_livros.html
, você pode usar os dados passados pela view para criar a página da web:
<!DOCTYPE html>
<html>
<head>
<title>Lista de Livros</title>
</head>
<body>
<h1>Lista de Livros</h1>
<ul>
{% for livro in livros %}
<li>{{ livro.titulo }} por {{ livro.autor }}</li>
{% endfor %}
</ul>
</body>
</html>
- {% for livro in livros %}: Aqui ele cria um "x" com o nome de
livro
, esse x vai passar por todos os itens que haver no "nome-representativo" chamadolivros
que interliga na views a variável chamadalivros
que você criou na etapa 4.1.2📌 OBS: Esse
{livros : livros}
que está na imagem de exemplo é igual a{nome-representativo : variável}
, pois criamos um "nome-representativo" para referenciar no HTML a "variável" informada na views, que é a variávellivros = Livro.objects.all()
.
- {{ livro.titulo }}: A lógica é parecida como as lógicas abordadas em programações da linguagem C, pegando um "x" que irá receber todos os valores de
titulo
1 por vez e apresentarem todas 1 por vez no HTML. Isso é a mesma coisa com o{{ livro.autor }}
também, é a mesma lógica de programação.- {% endfor %}: O FOR só irá acabar quando TODOS os itens de cada campo informado dentro dele (por exemplo,
{{ livro.titulo }}
) forem apresentados.
- Agora, você pode iniciar o servidor de desenvolvimento do Django e testar sua view, utilize runserver para testar o seu site como foi ensinado no 1.6.3
✔️ ▶ Lembre-se de ativar a sua Venv que foi ensinado no 1.2.4
🚫 ERROR - Caso você não ative:
✔️ ▶ Lembre-se de deixar o seu Banco de Dados MySQL ligado (XAMPP) como foi ensinado no 2.2.2
🚫 ERROR - Caso você não ligue:
✔️ ▶ Lembre-se de digitar a URL corretamente como imagem mostrada no 3.4
🚫 ERROR - Caso você não digite:
🗂️ - OBS: A página descreve quais URLs estão disponíveis
- Depois de tudo estiver em ordem, você poderá acessar a página com o Link que aparecerá quando você realizar o comando de Runserver.
- Os livros não foram adicionados ainda pelo FOR no HTML, pois não há nenhum livro registrado no seu banco.
EXTRA. Tornar a página como principal (index), sem a necessidade de digitar livros/
toda hora, para que ela possa aparecer sem essa necessidade.
🎛️ # Para tornar uma das páginas do seu app como principal (index), é necessário que você reconfigure a URL dessa página, é bem simples:
- Dessa forma o site assim que iniciar o servidor, irá te levar até a página diretamente sem a digitação na url.
🔔 # Nesta fase, você aprenderá a criar templates para renderizar páginas HTML e tornar sua aplicação mais dinâmica. Além disso, veremos como lidar com arquivos estáticos, criar templates parciais e layouts, e como gerenciar arquivos de mídia.
- Os templates HTML são usados para renderizar páginas da web com dados dinâmicos. Vamos criar um template simples para exibir detalhes de um livro.
1. Crie um arquivo HTML chamado livro_detalhes.html
em sua pasta de templates do aplicativo (por exemplo, Website/templates/livros_detalhes.html
).
- Depois de criar o HTML (template), você terá de vincula-lo a uma View ou URLs, volte as etapas anteriores para rever como criar uma View e URL na Fase 4: Views e URLs.
<!DOCTYPE html>
<html>
<head>
<!--CSS-->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css">
<link rel="stylesheet" href="style.css">
<!--Titulo-->
<title>Detalhes do Livro</title>
</head>
<body class="bg-gray">
<!--Header-->
<header class="bg-gray d-flex justify-content-center py-3">
<ul class="nav nav-pills">
<li class="nav-item"><a href="../" class="nav-link" aria-current="page">Listar</a></li>
<li class="nav-item"><a href="../detalhes" class="nav-link">Detalhes</a></li>
</ul>
</header>
<!--Main-->
<main class="bg-gray">
<img src="Exemplo-img.jpg" alt="">
{% for livro in livros %}
<h1 class="border-bottom border-danger">{{ livro.titulo }}</h1>
<p>Autor: {{ livro.autor }}</p>
<p>Data de Publicação: {{ livro.publicação }}</p>
<p>Número de Páginas: {{ livro.paginas }}</p>
{% endfor %}
</main>
<!--Footer-->
<footer class="bg-gray d-flex flex-wrap justify-content-between align-items-center py-3 my-4 border-top">
<div class="col-md-4 d-flex align-items-center">
<a href="https://github.com/DaviVidal01">
<img width="30px" src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/github/github-original.svg"/>
</a>
<span class="mb-3 mb-md-0 text-body-secondary">© 2023 WebBooks, copyright.</span>
</div>
<ul class="nav col-md-4 justify-content-end list-unstyled d-flex">
<li class="ms-3"><a class="text-body-secondary" href="https://github.com/DaviVidal01"><img width="30px" src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/github/github-original.svg"/></a></li>
<li class="ms-3"><a href="https://github.com/DaviVidal01/"><img src="https://camo.githubusercontent.com/cf57d31040e997c7ab2d909aedf085957c88cffe5f6e24b5a7d4d317b65d3689/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f666f6c6c6f776572732f44617669566964616c30313f6c6162656c3d666f6c6c6f77267374796c653d736f6369616c" data-canonical-src="https://img.shields.io/github/followers/DaviVidal01?label=follow&style=social" style="max-width: 100%;"></a></li>
</ul>
</footer>
<!--Scripts-->
<script src="bootstrap.bundle.min.js"></script>
</body>
</html>
Aqui foi utilizado alguns recursos do framework Bootstrap
📌 - É bem grande mesmo, pois estamos simulando um site completo agora, se você observar, terá comentários (
<!--Comentários-->
) marcando a posição de cada parte do HTML, por exemplo (CSS, Scripts, Header, Main, Footer, etc.). Se estiver trabalhando em equipe ou sozinho, é uma ótima forma de organizar o seu código.
- Mas ainda há coisas faltando nesse template, colocamos exatamente as informações, mas o site ainda não aparece todas as informações que pedi, como CSS, JS ou Imagem.
💻 - OBS: Não iniciei o server para mostrar o Site, apenas abri o HTML, por isso aparece os "{{ livro.titulo }}", pois apenas abrir um arquivo HTML não irá funcionar o banco.
- Agora você precisa configurar seu aplicativo para servir arquivos estáticos corretamente durante o desenvolvimento e implantação.
1. Abra o arquivo de configuração settings.py
, como por exemplo (WebBooks/setup/settings.py
) e coloque o codigo import os
no topo.
🔩 - Isso mostrará ao Django que o seu TEMPLATES está localizado no seu app em um arquivo chamado
templates
🔩 - Isso mostrará ao Django que o seu comando é
static
, que localiza a pasta através da URLstatic/
, onde os arquivos bases estão localizados emsetup/static
- Os arquivos estáticos, como CSS, JavaScript e imagens, podem ser usados para estilizar e enriquecer seu site. Vamos configurar os arquivos estáticos.
1. Crie uma pasta chamada static
no diretório setup do seu projeto (por exemplo, WebBooks/setup/static
)
2. Dentro dela crie subpastas para armazenar arquivos estáticos como css
, js
e img
logo depois adicione e carregue todos os arquivos CSS, JavaScript e Imagens nessas pastas conforme necessário.
3. No HTML onde está sendo utilizado esses recursos vão ser atualizado os códigos para Imagens e Links (Hrefs, Src, Script, etc.)
- Coloque o código
{% load static %}
no topo do HTML, pois ele serve para recarregar todos os componentes de dentro da pasta Static.- Modifique os codigos que contém Href, Src e Script que tiverem redirecionamento por diretórios como
src= 'css/style.css'
.- Na modificação você colocará o código
{% static 'seu-redirecionamento' %}
, por favor, respeite os espaços e a forma que é escrita o código, senão falhará.
- Exemplo:
🗂️ - OBS: Não há necessidade de fazer isso com Links "http" como no exemplo, eles não são links de pasta. Agora modifique todos os códigos que contem esses recursos de Href, Src ou Script para que seu site funcione corretamente.
- Seu codigo ficará assim:
{% load static %}
<!DOCTYPE html>
<html>
<head>
<!--CSS-->
<link rel="stylesheet" href="{% static './css/style.css' %}">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css">
<!--Titulo-->
<title>Detalhes do Livro</title>
</head>
<body class="bg-gray">
<!--Header-->
<header class="bg-gray d-flex justify-content-center py-3">
<ul class="nav nav-pills">
<li class="nav-item"><a href="../" class="nav-link" aria-current="page">Listar</a></li>
<li class="nav-item"><a href="../detalhes" class="nav-link">Detalhes</a></li>
</ul>
</header>
<!--Main-->
<main class="bg-gray">
<img width="60%" src="{% static './img/Exemplo-img.jpg' %}" alt="Livros">
{% for livro in livros %}
<h1 class="bg-gray border-bottom border-danger">{{ livro.titulo }}</h1>
<p class="bg-gray">Autor: {{ livro.autor }}</p>
<p>Data de Publicação: {{ livro.publicação }}</p>
<p>Número de Páginas: {{ livro.paginas }}</p>
{% endfor %}
</main>
<!--Footer-->
<footer class="bg-gray d-flex flex-wrap justify-content-between align-items-center py-3 my-4 border-top">
<div class="col-md-4 d-flex align-items-center">
<a href="https://github.com/DaviVidal01">
<img width="30px" src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/github/github-original.svg"/>
</a>
<span class="mb-3 mb-md-0 text-body-secondary">© 2023 WebBooks, copyright.</span>
</div>
<ul class="nav col-md-4 justify-content-end list-unstyled d-flex">
<li class="ms-3"><a class="text-body-secondary" href="https://github.com/DaviVidal01"><img width="30px" src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/github/github-original.svg"/></a></li>
<li class="ms-3"><a href="https://github.com/DaviVidal01/"><img src="https://camo.githubusercontent.com/cf57d31040e997c7ab2d909aedf085957c88cffe5f6e24b5a7d4d317b65d3689/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f666f6c6c6f776572732f44617669566964616c30313f6c6162656c3d666f6c6c6f77267374796c653d736f6369616c" data-canonical-src="https://img.shields.io/github/followers/DaviVidal01?label=follow&style=social" style="max-width: 100%;"></a></li>
</ul>
</footer>
<!--Scripts-->
<script src="{% static './js/bootstrap.bundle.min.js' %}"></script>
</body>
</html>
- {% load static %}: Isso carrega os arquivos estáticos para que você possa usar a tag
{% static %}
para referenciar seus arquivos CSS, JavaScript, imagens, etc.- {% static 'css/style.css' %}: Isso carrega um arquivo CSS estático usando a tag
{% static %}
, pegando o arquivo que está dentro da pastastatic
.
4. Abrir o terminal ou prompt de comando e navegar até o diretório Raiz/Pai do seu projeto e realizar o comando:
python ./manage.py collectstatic
-
Se já tiver arquivos dentro da pasta Static, ele vai perguntar se deseja copia-los, ele logo enviará a cópia para onde os arquivos static que você redirecionou na
settings.py
-
Por fim quando você iniciar o Runserver ensinado na etapa 1.6.3, e depois digitar a URL
detalhes/
, seu site carregará todos os Statics, carregará o Banco e ficará assim:
- Modelos parciais, também conhecidos como "partials," são partes reutilizáveis de um modelo HTML que você pode incluir em várias páginas. Eles são úteis para manter seu código limpo e evitar a duplicação de HTML.
1. Navegue até a pasta templates
dentro do seu app e crie uma pasta chamada partials
(exemplo Website/templates/partials
).
2. Crie 2 arquivos HTML dentro dessa pasta partials
, um chamado footer.html
e outro header.html
, dentro de cada um deles será colocado os seguintes códigos.
🔔 # Lembra dos comentários do seu HTML? (exemplo,
<!--HEADER-->
), você pegará cada parte do código que está dentro do<body>...</body>
, como o<!--HEADER-->
e<!--FOOTER-->
Footer:
<footer class="bg-gray d-flex flex-wrap justify-content-between align-items-center py-3 my-4 border-top">
<div class="col-md-4 d-flex align-items-center">
<a href="https://github.com/DaviVidal01">
<img width="30px" src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/github/github-original.svg"/>
</a>
<span class="mb-3 mb-md-0 text-body-secondary">© 2023 WebBooks, copyright.</span>
</div>
<ul class="nav col-md-4 justify-content-end list-unstyled d-flex">
<li class="ms-3"><a class="text-body-secondary" href="https://github.com/DaviVidal01"><img width="30px" src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/github/github-original.svg"/></a></li>
<li class="ms-3">
<a href="https://github.com/DaviVidal01/">
<img src="https://camo.githubusercontent.com/cf57d31040e997c7ab2d909aedf085957c88cffe5f6e24b5a7d4d317b65d3689/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f666f6c6c6f776572732f44617669566964616c30313f6c6162656c3d666f6c6c6f77267374796c653d736f6369616c" data-canonical-src="https://img.shields.io/github/followers/DaviVidal01?label=follow&style=social" style="max-width: 100%;">
</a>
</li>
</ul>
</footer>
Header:
<header class="bg-gray d-flex justify-content-center py-3">
<ul class="nav nav-pills">
<li class="nav-item"><a href="../" class="nav-link" aria-current="page">Listar</a></li>
<li class="nav-item"><a href="../detalhes" class="nav-link">Detalhes</a></li>
</ul>
</header>
- Não esqueça de colocar o
{% load static %}
no topo dos HTMLsheader.html
efooter.html
3. Agora no lugar de onde você tirou o código de cada um desses 2 comentários, você substituirá por {% include 'partials/nome-do-html' %}
, como está no exemplo:
-Se você testar com Runserver ensinado na etapa 1.6.3, poderá ver quer o Footer e o Header estão todos ali.
- Outra forma de identifica-los é indo em Inspecionar Elemento (
botão direito do mouse
)
{% load static %}
<!DOCTYPE html>
<html>
<head>
<!--CSS-->
<link rel="stylesheet" href="{% static './css/style.css' %}">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css">
<!--Titulo-->
<title>Lista de Livros</title>
</head>
<body class="bg-gray">
<!--Header-->
{% include 'partials/header.html' %}
<!--Main-->
<main class="bg-gray">
<h1>Lista de Livros</h1>
<ul>
{% for livro in livros %}
<li>{{ livro.titulo }} por {{ livro.autor }}</li>
{% endfor %}
</ul>
</main>
<!--Footer-->
{% include 'partials/footer.html' %}
<!--Scripts-->
<script src="{% static './js/bootstrap.bundle.min.js' %}"></script>
</body>
</html>
📌 # Lembrando que Partials é bastante criado para que não haja repetições de códigos, caso você tenha várias páginas com o mesmo navbar(Header) e o mesmo footer, você pode estar utilizando partials além de várias outras para facilitar seu código e não necessitar escrever linhas e linhas repetidamente.
🔔 # Para manter seu código mais organizado, você pode criar na pasta
templates
os layouts. Por exemplo, você pode criar um arquivobase.html
que define o layout geral do site e usar tags de inclusão para incluir outros templates parciais.
2. Coloque o conteúdo base que tem em todas as páginas do seu site em base.html
, como o HEAD, BODY, SCRIPTS e CSS para que não haja repetição de código.
{% load static %}
<!DOCTYPE html>
<html>
<head>
<!--CSS-->
<link rel="stylesheet" href="{% static './css/style.css' %}">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css">
<!--Titulo-->
<title>{% block title %}WebBooks - {% endblock %}</title>
</head>
<body class="bg-gray">
{% block content %}
{% endblock %}
<!--Scripts-->
<script src="{% static './js/bootstrap.bundle.min.js' %}"></script>
</body>
</html>
- {% block content %}: Este é um bloco de conteúdo que outras páginas estendidas podem preencher com seu próprio conteúdo, ela se estende até onde o codigo localizar o chamado
{% endblock %}
.- {% block title %}: Este é um bloco que permite que outras páginas estendam este modelo e forneçam seu próprio título, ela se estende até onde o codigo localizar o chamado
{% endblock %}
.📌 # Outros templates podem estender o
base.html
e preencher os blocos de conteúdo.
3. Agora podemos substituir os códigos repetidos por {% block content %}
(para determinar o início do conteúdo) e {% endblock %}
(para determinar o fim do conteúdo)
- É importante que o comando
{% extends 'base.html' %}
esteja no topo de tudo, pois ele determina qual é o Layout base para a página preencher os conteúdos.
lista_livros.html:
{% extends 'base.html' %}
{% load static %}
{% block content %}
<title>{% block title %}Lista de Livros{% endblock %}</title>
<!--Header-->
{% include 'partials/header.html' %}
<!--Main-->
<main class="bg-gray">
<h1>Lista de Livros</h1>
<ul>
{% for livro in livros %}
<li>{{ livro.titulo }} por {{ livro.autor }}</li>
{% endfor %}
</ul>
</main>
<!--Footer-->
{% include 'partials/footer.html' %}
{% endblock %}
livro_detalhes.html:
{% extends 'base.html' %}
{% load static %}
{% block content %}
<title>{% block title %}Livro Detalhes{% endblock %}</title>
<!--Header-->
{% include 'partials/header.html' %}
<!--Main-->
<main class="bg-gray">
<img width="60%" src="{% static './img/Exemplo-img.jpg' %}" alt="Livros">
{% for livro in livros %}
<h1 class="bg-gray border-bottom border-danger">{{ livro.titulo }}</h1>
<p class="bg-gray">Autor: {{ livro.autor }}</p>
<p>Data de Publicação: {{ livro.publicação }}</p>
<p>Número de Páginas: {{ livro.paginas }}</p>
{% endfor %}
</main>
<!--Footer-->
{% include 'partials/footer.html' %}
{% endblock %}
- Depois de preencher corretamente e iniciar o Runserver ensinado na etapa 1.6.3, você poderá ver que o site funcionará normalmente, pois as Partials e Layout (base.html) se juntam com os templates formando um "Quebra-Cabeça".
🔔 # Dessa forma, você pode criar páginas HTML de maneira organizada, estendendo um modelo principal e preenchendo os blocos de conteúdo conforme necessário. Isso torna seu código mais modular e fácil de gerenciar.
- Arquivos de mídia, como imagens enviadas pelos usuários dentro do seu site, podem ser armazenados em uma pasta separada. Configure as configurações de mídia no
settings.py
que fica localizado na setup do seu site (exemplo,WebBooks/setup/settings.py
).
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
🎛️ - Esse código faz com que o Django encontre a pasta chamada
media
dentro do seu diretório Raiz/Pai do projeto, e lá ele começará a armazenar dados e informações como imagens, arquivos, etc. Que forem adicionados pelos usuários de seu site, ou até mesmo pelos adm.
2. Ainda no diretório do seu setup
procure o arquivo chamado urls.py
, normalmente localizado abaixo do arquivo settings.py
e escreva os seguintes códigos
No topo:
from django.conf import settings
from django.conf.urls.static import static
Nas últimas linhas:
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
- Exemplo:
- Agora você está pronto para usar arquivos de mídia em sua aplicação.
4. Vamos agora reconfigurar a models.py
para que possa receber imagens adicionadas pelo SUPERUSER e armazena-las, além de exibi-las no site lista_livros.html
Models Atualizado:
from django.db import models
# Create your models here.
class Livro(models.Model):
titulo = models.CharField(max_length=200)
autor = models.CharField(max_length=100)
capa = models.ImageField(default='', upload_to= './images')
#Dentro da pasta Media vai ser criada images que armazenará esses itens
publicação = models.DateField()
paginas = models.IntegerField()
- Realiza o
python ./manage.py makemigrations
e vai gerar um ERRO:
- Você irá baixar o Pillow, lembre-se de estar com a Venv ligada.
python -m pip install Pillow
- Agora realize o
makemigrations
emigrate
para que a atualização do banco possa ser completada.
- Vamos atualizar também a página
lista_livros.html
para que ele possa exibir essas informações
{% extends 'base.html' %}
{% load static %}
{% block content %}
<title>{% block title %}Lista de Livros{% endblock %}</title>
<!--Header-->
{% include 'partials/header.html' %}
<!--Main-->
<main class="bg-gray">
<h1>Lista de Livros</h1>
<ul>
{% for livro in livros %}
<li>{{ livro.titulo }} por {{ livro.autor }}</li>
<li>
{% if livro.capa %}
<img src="{{ livro.capa.url }}" alt="capa-de-livros" width="10%">
{% else %}
<p>Capa não encontrada</p>
{% endif %}
</li>
{% endfor %}
</ul>
</main>
<!--Footer-->
{% include 'partials/footer.html' %}
{% endblock %}
- {{ livro.capa.url }}: O contador "livro" pega as informações adicionadas no campo "capa" e redireciona sua URL para dentro do
src
assim apresentando todas as imagens por vez, por conta do contador estar dentro do FOR.📌 - Os contadores sempre são identificados como IDs, então para apresentar imagens ou itens separadamente, utiliza-se
{{ 1.capa.url }}
por exemplo. Isso funciona para outros recursos e campos também, tudo que é feito no banco deve a ser identificado a partir de sua Primary_Key.
🔔 # Nesta fase, você entenderá como o padrão MVT funciona no Django, que é semelhante ao famoso padrão MVC (Model-View-Controller), e como integrar os modelos, views e templates para criar páginas da web dinâmicas.
Entendendo o Padrão MVT:
Model (Modelo):
Os modelos representam a estrutura dos dados e a lógica de negócios. Eles são responsáveis por interagir com o banco de dados e fornecer dados para as views.View (Visão):
As views são responsáveis por processar solicitações HTTP, interagir com os modelos para obter dados e renderizar as respostas. As views geralmente correspondem às páginas da web.Template (Modelo de Apresentação):
Os templates são arquivos HTML que definem como os dados serão apresentados. Eles usam a linguagem de modelo do Django para inserir dados dinâmicos nas páginas.
📝 # Você já integrou a Model com o Template utilizando a Views nas etapas anteriores, então essa fase é apenas para estudar o MVT que já fizemos, vamos pegar uma parte dos códigos para analisa-los.
view.py:
from django.shortcuts import render
from .models import Livro
def lista_livros(request):
livros = Livro.objects.all()
return render(request, 'myapp/lista_livros.html', {'livros': livros})
lista_livros.html:
<!DOCTYPE html>
<html>
<head>
<title>Lista de Livros</title>
</head>
<body>
<h1>Lista de Livros</h1>
<ul>
{% for livro in livros %}
<li>{{ livro.título }} por {{ livro.autor }}</li>
{% endfor %}
</ul>
</body>
</html>
- A view (view.py) chama o modelo (Livro) para obter dados dos livros adicionados.
- A view passa esses dados para o template.
- O template usa a linguagem de modelo do Django (as tags
{% %}
e{{ }}
) para exibir os dados na página.
- Dessa forma, o padrão MVT do Django permite que você crie páginas da web dinâmicas, onde os dados são buscados a partir dos modelos, processados nas views e apresentados nos templates.
- O modelo é responsável por lidar com os dados do aplicativo, definindo sua estrutura e manipulação.
- Representa o acesso aos dados, incluindo a leitura, gravação e consulta de informações no banco de dados.
- Os modelos no Django são representados como classes Python que definem a estrutura do banco de dados.
- Os modelos são independentes da camada de interface do usuário e do controle de visualização.
- A camada de visualização lida com a lógica da aplicação e controla o fluxo de informações entre o modelo e o template.
- As visualizações recebem solicitações do navegador do usuário, processam essas solicitações e interagem com o modelo para buscar ou salvar dados.
- Eles também decidem qual template deve ser usado para renderizar a resposta.
- As visualizações são escritas em Python e podem retornar respostas em HTML, JSON, XML ou outros formatos.
- Os modelos de apresentação (templates) são responsáveis pela renderização de HTML e pela apresentação da interface do usuário.
- Eles definem como os dados são exibidos nas páginas da web, combinando conteúdo estático e dinâmico.
- Os templates utilizam uma linguagem de marcação especial chamada Django Template Language (DTL) para inserir variáveis, estruturas condicionais e loops nos modelos.
- Os templates são projetados para serem reutilizáveis e podem incluir tags, filtros e blocos para facilitar a criação de páginas consistentes.
- Quando um usuário acessa uma página no aplicativo, uma solicitação é enviada para o servidor Django.
- A visualização apropriada é mapeada para essa solicitação com base nas configurações de URL.
- A visualização interage com o modelo, se necessário, para recuperar ou salvar dados no banco de dados.
- A visualização seleciona o template a ser usado para renderizar a resposta.
- O template usa o Django Template Language para preencher o conteúdo dinâmico com base nos dados do modelo.
- A resposta é gerada e enviada de volta para o navegador do usuário.
🔩 # Essa arquitetura facilita a separação de preocupações em um aplicativo Django. Os modelos cuidam dos dados, as visualizações tratam da lógica e as templates controlam a apresentação. Isso torna o desenvolvimento mais organizado e permite que diferentes partes do aplicativo sejam modificadas independentemente.
🔔 # O Django fornece um painel de administração integrado que facilita a tarefa de gerenciar os dados de seu aplicativo. Nesta fase, você aprenderá a habilitar e personalizar o painel de administração do Django.
💼 # Nós já criamos um superusuário e colocando os comandos no arquivo
admin.py
de dentro do seu app, é só seguir as etapas 3.3 e 3.4.
- Mas escrevendo apenas
admin.register(Livro)
não possibilitará a criação de novos Livros, apenas conseguirá ver todos os registros de cada Livro, então adicione.site
no meio como no exemplo:
admin.py:
Visualização:
💼 # Você pode personalizar a interface de administração do Django de várias maneiras, como a seguir:
- ModelAdmin: Você pode criar uma classe
ModelAdmin
para personalizar a forma como os modelos são exibidos no painel de administração. Por exemplo, você pode definir campos para serem exibidos, filtros e ações personalizadas.
from django.contrib import admin
from .models import Livro
@admin.register(Livro)
class LivroAdmin(admin.ModelAdmin):
list_display = ('titulo', 'autor', 'publicação')
list_filter = ('autor', 'publicação')
Visualização:
- list_display = ('titulo', 'autor', 'publicação'): Ele acaba exibindo as informações de Titulo, Autor e Publicação na página do Admin, como informações principais.
- list_filter = ('autor', 'publicação'): É utilizado o Autor e Publicação (data) para filtrar os Livros, você consegue filtrar vários livros que foram feitos por 1 Autor ou em uma data/ano específico.
📚 OBS: O livro que está adicionado, foi criado para a realização do teste, vamos aprender a adicionar itens no Django Admin na próxima etapa.
🔩 # É importante lembrar que se o seu models (banco de dados) estiver com mais detalhes e campos, ficará mais interessante usar e abusar dessas personalizações.
- No nosso caso, apresentarei apenas as personalizações que ficaram bons para esse Models Simples
Filtros Simples:
list_filter = ('autor', 'publicação')
#Aqui ele criará filtros com esses 2 campos
Lista de Apresentação
:
list_display = ('titulo', 'autor', 'publicação')
#Aqui ele apresentará esses 3 campos
Barra de Pesquisa:
search_fields = ('titulo', 'autor')
#Aqui ele só procurará pesquisas referentes a esses 2 campos.
Complementação de Dados:
fieldsets = [
('Informações Básicas', {'fields': ['titulo', 'autor', 'publicação']}),
('Detalhes Adicionais', {'fields': ['paginas', 'capa']}),
]
#Aqui ele separará o formulário do admin com 2 etapas "Informações Básicas" e "Detalhes Adicionais"
Como o código é escrito:
- Para mais personalizações, você pode estar pesquisando na documentação do Django Admin ou pesquisando em outras fontes.
📚 # Essa etapa não tem muito segredo, é uma interface bem simples de se usar.
- Você possui 2 opções, "Add" ou "Change",
Add
servirá para adicionar novos itens enquanto oChange
servirá para edita-los.
📚 # Nesse ambiente você poderá preencher as lacunas com as informações necessárias e depois escolher entre as 3 opções
- Salvar: Salvar e Sair.
- Salvar e Adicionar Outro: Salvar e começar a editar outra ficha.
- Salvar e Continuar Editando: Salvar e continuar na mesma ficha, caso ela seja grande demais ou queira usar para testes.
- Quando salvar e abrir o Workbench MySQL, poderá ver que seus itens adicionados estaram no banco registrados.
Para ver siga as instruções:
Passo 1: Abrir o Servidor
Passo 2: Entrar no Schema
Passo 3: Localizar o seu Schema
Passo 4: Clicar na mini-tabela
Passo 5: Admirar seu item no banco
Passo 6: Realizar Runserver e ver seus itens no site
lista_livros:
livro_detalhes:
🔔 # Essa parte é configurada quando se está trabalhando em equipe para algum serviço grande, podendo permitir ou negar acesso de certos usuários que estão tentando entrar no
admin/
- Os "Users" (Usuários) se referem aos indivíduos que têm acesso à sua aplicação. Cada usuário possui uma conta única, geralmente identificada por um nome de usuário (username) e uma senha.
- Usuários são responsáveis por autenticar na aplicação (fazer login) e interagir com funcionalidades específicas com base nas permissões concedidas a eles.
- No Django, o modelo de usuário padrão já está incluído e é altamente configurável. Você pode adicionar informações personalizadas aos perfis de usuário, como nome completo, endereço de e-mail, etc.
- Os usuários também podem ser atribuídos a grupos para facilitar o gerenciamento de permissões.
- Os "Groups" (Grupos) são conjuntos lógicos de permissões. Eles são usados para organizar usuários com permissões semelhantes em categorias ou grupos.
- Em vez de atribuir permissões a cada usuário individualmente, você pode criar grupos com permissões predefinidas e, em seguida, atribuir usuários a esses grupos.
- Isso simplifica a administração de permissões, especialmente quando você tem muitos usuários com as mesmas permissões.
- Por exemplo, você pode criar grupos como "Admins," "Editores," "Leitores," e atribuir as permissões apropriadas a cada grupo.
- Em seguida, você pode adicionar ou remover usuários desses grupos para conceder ou revogar permissões em lote.
- No Django admin, você pode gerenciar usuários e grupos na seção "Authentication and Authorization".
- Você pode criar, editar e excluir usuários, bem como criar e gerenciar grupos.
- Ao criar ou editar um usuário, você pode definir seu nome de usuário, senha e outras informações. Além disso, você pode especificar a qual grupo o usuário pertence.
- Ao configurar permissões para um grupo, você define o que os usuários desse grupo podem fazer em relação aos modelos (tabelas do banco de dados) da sua aplicação. Isso inclui permissões de visualização, adição, alteração e exclusão.
- No modelo padrão de autenticação do Django, há grupos predefinidos, como "Admin," "Staff," e "Superuser," cada um com diferentes conjuntos de permissões. Você pode personalizar esses grupos ou criar novos de acordo com suas necessidades.
🎛️ # Vamos agora traduzir a página do seu Admin Django, para que seja da sua facilidade de leitura.
1. Para traduzir o painel admin do Django, você deverá ir até o arquivo settings.py
do seu projeto (WebBooks/setup/settings.py
)
2. Vá até a seção de LANGUAGE_CODE, lá você substituirá os códigos do TIME_ZONE e LANGUAGE_CODE para:
LANGUAGE_CODE = 'pt-br'
TIME_ZONE = 'America/Sao_Paulo'
🔔 # Agora você pode usar o painel de administração para adicionar, editar e excluir registros de seu banco de dados de forma conveniente. Nesta fase, você aprendeu a habilitar e personalizar o painel de administração do Django. Na próxima fase, exploraremos como criar formulários e lidar com validação de dados.
🔔 # Nesta fase, você aprenderá como criar formulários para coletar dados do usuário e como realizar a validação desses dados.
- Para criar um formulário, você deve criar uma classe que herde de
forms.Form
. Vamos criar um exemplo de formulário para adicionar novos livros:
- Os campos de dentro de
LivroForm
devem ser iguais aos que foram criados nomodels.py
, 'titulo', 'autor', 'publicação', 'paginas' e 'capa'.
from django import forms
class LivroForm(forms.ModelForm):
class Meta:
model = Livro
fields = '__all__'
- Forms que estamos utilizando:
- forms.ModelForm: Ele importa recursos de
forms
, recursos esses guardados emModelForm
e adiciona dentro daclass
.- class Meta: Dentro da classe
LivroForm
, há uma classe aninhada chamadaMeta
. Essa classeMeta
é usada para fornecer metadados ao formulário.- model = Livro: O atributo model dentro da classe
Meta
especifica qual modelo do Django este formulário está associado. Neste caso, é associado ao modeloLivro
.fields = '__all__':
O atributo fields determina quais campos do modelo Livro serão incluídos no formulário.__all__
significa que todos os campos do modelo serão incluídos no formulário.
- Aqui tem outros exemplos de forms:
- forms.Form: Ele importa recursos de
forms
, recursos esses guardados emForm
e adiciona dentro daclass
.- forms.CharField: Pega de
forms
a ferramenta chamadaCharField
que registra Caracteres.- forms.DateField: Pega de
forms
a ferramenta chamadaDateField
que registra Datas.- forms.IntegerField: Pega de
forms
a ferramenta chamadaIntegerField
que registra Números Inteiros.- forms.ImageField: Pega de
forms
a ferramenta chamadaImageField
que registra arquivos ImagensMais informações de ferramentas de armazenamento no banco de dados
Field
estão na documentação do Django Models Field References
- Agora que você criou o formulário, você pode renderizá-lo em uma view.
2. Importe o formulário que você criou no topo do código e adiciona ao lado de "render
" um chamado redirect
para redirecionamento de páginas:
Ficará assim:
from django.shortcuts import render, redirect
from .models import Livro
from .forms import LivroForm
def adicionar_livro(request):
if request.method == 'POST':
livro_form = LivroForm(request.POST, request.FILES)
if livro_form.is_valid():
novo_livro = Livro(
titulo= livro_form.cleaned_data['titulo'],
autor= livro_form.cleaned_data['autor'],
publicação= livro_form.cleaned_data['publicação'],
paginas= livro_form.cleaned_data['paginas'],
capa = livro_form.cleaned_data['capa']
)
novo_livro.save()
return redirect('lista_livros')
else:
livro_form = LivroForm()
return render(request, 'adicionar_livro.html', {'livro_form': livro_form})
- def adicionar_livro(request): Isso define uma função de view chamada
adicionar_livro
que é chamada quando alguém acessa a URL correspondente.- if request.method == 'POST': Esta linha verifica se a solicitação é uma solicitação
POST
. Em Django, isso geralmente é usado para processar formulários enviados. Se a solicitação for umPOST
, significa que alguém enviou um formulário de adição de livro.- livro_form = LivroForm(request.POST, request.FILES): Aqui, estamos criando uma instância do formulário
LivroForm
com os dados da solicitaçãoPOST
. Estamos passando tantorequest.POST
quantorequest.FILES
, porque este formulário inclui um campo de upload de arquivo para a capa do livro e orequest.FILES
contribui para o tratamento desses arquivos.- if livro_form.is_valid(): Esta linha verifica se os dados fornecidos no formulário são válidos de acordo com as regras definidas no formulário
LivroForm
. Se o formulário for válido, isso significa que os dados do livro são preenchidos corretamente.- novo_livro = Livro(...): Aqui, estamos criando uma instância do modelo
Livro
com base nos dados fornecidos no formulário (Os campos tem de terem o mesmo nome que o Formulário). Estamos pegando os valores do 'título', 'autor', 'data de publicação', 'número de páginas' e a 'capa' do formulário e atribuindo-os a um novo objetoLivro
.- novo_livro.save(): Esta linha salva o novo livro no banco de dados. Após a execução desta linha, o livro será armazenado permanentemente no banco de dados.
- return redirect('lista_livros'): Após salvar o livro com sucesso, redirecionamos o usuário para a página '
lista_livros
', que exibirá a lista atualizada de livros.- else: Se a solicitação não for um
POST
, isso significa que é a primeira vez que alguém acessa a página ou enviou um formulário inválido.- livro_form = LivroForm(): Aqui, estamos criando uma instância vazia do formulário
LivroForm
. Isso é feito para exibir um formulário em branco para o usuário quando ele acessa a página pela primeira vez.- return render(request, 'adicionar_livro.html', {'livro_form': livro_form}): Se a solicitação não for um
POST
, estamos renderizando a página 'adicionar_livro.html
' e passando o formuláriolivro_form
como contexto. Isso exibe o formulário em branco para o usuário, para que possa ser repreenchido corretamente.
- Agora você precisa criar um template HTML para o formulário. Vamos criar um arquivo chamado
adicionar_livro
.html em sua pasta de templates.
{% extends 'base.html' %}
{% load static %}
{% block content %}
<title>{% block title %}Adicionar Livro{% endblock %}</title>
<!--Header-->
{% include 'partials/header.html' %}
<main>
<h1>Adicionar Livro</h1>
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ livro_form.as_p }}
<button type="submit">Adicionar Livro</button>
</form>
</main>
<!--Footer-->
{% include 'partials/footer.html' %}
{% endblock %}
- method="post" enctype="multipart/form-data": Aqui, você está criando um elemento de formulário HTML usando a tag
<form>
. O atributomethod
está definido como "post", o que significa que o formulário será enviado como uma solicitaçãoPOST
quando o usuário o enviar. O atributoenctype
está definido como "multipart/form-data". Isso é necessário quando você tem campos de entrada do tipo "file" (como o campo de upload de imagem), pois permite o envio de arquivos binários. O valor "multipart/form-data" é usado para formulários que contêm campos de upload de arquivo.- {% csrf_token %}: Esta é uma tag do Django template que insere um token de segurança
CSRF (Cross-Site Request Forgery)
no formulário. Isso é importante para proteger seu aplicativo contra ataquesCSRF
. Quando o formulário é enviado, o Django verifica se o token é válido.- {{ livro_form.as_p }}: Esta é outra tag do Django template.
livro_form
é uma instância do seu formulárioLivroForm
.as_p
é um método que renderiza o formulário com cada campo(título, autor, etc.)
em um parágrafo(<p>)
. Isso cria uma representação simples do formulário, onde cada campo do formulário é exibido em um novo parágrafo.- type="submit": Este é colocado em um botão de envio no formulário. Quando o usuário clica neste botão, o formulário é enviado para o servidor. O atributo type está definido como "submit", o que significa que este botão é usado para enviar o formulário. O texto "Adicionar Livro" é o rótulo do botão exibido para o usuário.
🎨 OBS: Tem várias outras formas de criar Inputs personalizados, utilizando CSS/HTML, além de outras formas de apresentar o formulário, basta usar a criatividade.
- Vamos mudar algumas coisas no nosso Header, localizado dentro do
templates/partials/header.html
header.html:
{% load static %}
<header class="bg-gray d-flex justify-content-center py-3">
<ul class="nav nav-pills">
<li class="nav-item"><a href="../" class="nav-link" aria-current="page">Listar</a></li>
<li class="nav-item"><a href="../detalhes" class="nav-link">Detalhes</a></li>
<li class="nav-item"><a href="../adicionar" class="nav-link">Adicionar</a></li>
</ul>
</header>
- Você pode personalizar a aparência dos campos do formulário usando CSS. Vou fornecer um exemplo de como você pode criar inputs com labels mais estilizados
adicionar_livro.html: (Cole onde fica o form)
<form method="post" enctype="multipart/form-data" action="{% url 'adicionar_livro' %}">
{% csrf_token %}
<div class="form-group">
<label for="{{ livro_form.titulo.id_for_label }}">Título:</label>
{{ livro_form.titulo }}
</div>
<div class="form-group">
<label for="{{ livro_form.autor.id_for_label }}">Autor:</label>
{{ livro_form.autor }}
</div>
<div class="form-group">
<label for="{{ livro_form.publicacao.id_for_label }}">Data de Publicação:</label>
{{ livro_form.publicacao }}
</div>
<div class="form-group">
<label for="{{ livro_form.paginas.id_for_label }}">Número de Páginas:</label>
{{ livro_form.paginas }}
</div>
<div class="form-group">
<label for="{{ livro_form.capa.id_for_label }}">Capa do Livro:</label>
{{ livro_form.capa }}
</div>
<button type="submit">Adicionar Livro</button>
</form>
style.css: (Cole isso nos dois arquivos style.css localizado nas 2 pastas STATIC criadas)
/* Estilos gerais para o formulário */
.form-group {
margin-bottom: 20px;
}
label {
font-weight: bold;
display: block;
}
/* Estilos para os inputs */
input[type="text"],
input[type="date"],
input[type="number"],
input[type="file"],
input[type="password"]{
width: 100%;
padding: 10px;
border: 1px solid #ccc;
border-radius: 5px;
font-size: 16px;
}
/* Estilos para o botão */
button {
background-color: #007BFF;
color: #fff;
padding: 10px 20px;
border: none;
border-radius: 5px;
cursor: pointer;
}
button:hover {
background-color: #0056b3;
}
- Realize o comando e depois o Runserver:
python manage.py collectstatic
- action="{% url 'adicionar_livro' %}": O atributo action em uma tag
<form>
define para onde os dados do formulário serão enviados quando o usuário o submeter. Neste caso, "{% url 'adicionar_livro' %}
" é uma tag do Django que resolve dinamicamente a URL para a view chamada 'adicionar_livro
'. Isso significa que quando o formulário é enviado, os dados serão processados pela view chamada 'adicionar_livro
'.- for="{{ livro_form.autor.id_for_label }}": Esse é um atributo for de uma tag
<label>
. As tags<label>
são usadas para rotular campos de entrada em um formulário. Neste caso, o atributo for está configurado para o campo 'autor
' do formulário(livro_form.autor)
. O valorlivro_form.autor.id_for_label
é uma forma dinâmica de gerar um ID para o campo de entrada 'autor
'. Isso está relacionado à acessibilidade, permitindo que a etiqueta esteja associada corretamente ao campo de entrada. Dessa forma, quando o usuário clica no rótulo, o foco é direcionado para o campo 'autor
'.- {{ livro_form.autor }}: Esta é uma variável do Django template que renderiza o campo de entrada '
autor
' do formulário. O que é renderizado depende do tipo do campo 'autor
' em seu formulário. Se for um campoCharField
, por exemplo, isso renderizará um campo de texto de entrada. Se for um campoDateField
, renderizará um campo de entrada de data. O Django gera automaticamente o HTML necessário para o campo, com base nas configurações do campo no formulário.
- Vamos agora para o arquivo
urls.py
do seu aplicativo.
urls.py:
from django.urls import path
from . import views
urlpatterns = [
path('', views.lista_livros, name='lista_livros'),
path('detalhes/', views.livro_detalhes, name="livro_detalhes"),
# ----- FORM Livro
path('adicionar/', views.adicionar_livro, name="adicionar_livro"),
]
🎨 # OBS: Foi colocado um comentário chamado FORM livro, para poder separar qual é a função daquela URL, isso deixa mais organizado 🎨 # OBS 2: Lembrando que ao inserir data, você deve inseri-la usando tracinhos como
2023-10-17
pois está na formatação EUA, por exemplo:
- Para configurar a autenticação de usuários, você pode aproveitar as funcionalidades incorporadas do Django, ele próprio já oferece configurações e recursos padrões de banco para Usuários, Authenticação, Groups (Admins), entre outros, nessa etapa iremos usar a configuração padrão de Usuários do Django, como podemos ver no banco Workbench e nas configurações do
settings.py
.
🔔 # Coloque dentro do arquivo
urls.py
que está localizado dentro do seu aplicativoWebsite/urls.py
os seguintes comandos, colocamos as viewslogin_view
elogout_view
, mas ainda não criamos eles, vamos criar na próxima etapa.
urlpatterns = [
# Outras URLs
path('login_user/', views.login_view, name='login_user'),
path('logout_user/', views.logout_view, name='logout_user'),
]
Exemplo:
🔔 # Agora, em seu arquivo
navbar.html
, você pode adicionar os botões de "Login
" e "Logout
". Você pode usar Bootstrap para estilizá-los da maneira desejada. Aqui está um exemplo:
{% load static %}
<header class="bg-gray d-flex justify-content-center py-3">
<ul class="nav nav-pills">
<li class="nav-item"><a href="../" class="nav-link" aria-current="page">Listar</a></li>
<li class="nav-item"><a href="../detalhes" class="nav-link">Detalhes</a></li>
<li class="nav-item"><a href="../adicionar" class="nav-link">Adicionar</a></li>
</ul>
{% if user.is_authenticated %}
<a href="{% url 'logout_user' %}" class="btn btn-primary">Logout</a>
{% else %}
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#modalLogin">Login</button>
{% endif %}
</header>
Exemplo:
- {% if user.is_authenticated %}: Isso é uma declaração condicional em Django Template Language (DTL). Aqui, estamos verificando se o usuário atual está autenticado, ou seja, se já fez login. Se o usuário estiver autenticado, o bloco de código dentro deste
if
será executado.<a href="{% url 'logout_user' %}" class="btn btn-primary">Logout</a>:
Dentro do blocoif
, estamos criando um link(<a>)
que levará o usuário para a URL de logout_user. A URL é definida com{% url 'logout_user' %}
, que se refere à visualização delogout_user
do Django. Além disso, a classe "btn btn-primary
" é aplicada para estilizar o link como um botão.- {% else %}: Esta parte é executada se o usuário não estiver autenticado (ou seja, o inverso da condição no
if
).<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#modalLogin">Login</button>:
Se o usuário não estiver autenticado, esta linha de código cria um botão<button>
com o texto "Login
". Os atributosdata-bs-toggle="modal"
edata-bs-target="#modalLogin"
são parte do Bootstrap e são usados para ativar o modal quando o botão é clicado. Oclass="btn btn-primary"
estiliza o link como um botão primário.
🔔 # Vamos criar um formulário de login no Django. Primeiro, você precisa criar um novo formulário no seu
forms.py
:
class LoginForm(forms.Form):
username = forms.CharField(label="Username", required=True, max_length=100)
password = forms.CharField(label="Senha", required=True, max_length=100, widget=forms.PasswordInput(attrs={'type':'password'}))
Exemplo:
🔔 # Vamos criar agora as views de Logout e Login, no nosso caso vamos fazer com que o login, além de reconhecer o nome de usuário (username) ele também poderá logar a partir de email, então teremos alguns comandos adicionais no nosso código da view
login_view
:
login_view:
from django.contrib.auth import login, logout
from django.contrib import auth
from django.shortcuts import render, redirect
from django.contrib import messages
def login_view(request):
login_form = LoginForm()
# Verifica se o formulário possui método POST
if request.method == 'POST':
login_form = LoginForm(request.POST)
#Verifica se os dados inseridos no formulário são válidos
if login_form.is_valid():
#Pega os dados do formulário de seus específicos names
username = login_form['username'].value()
password = login_form['password'].value()
#Faz a authenticação do usuário para verificar seus dados
usuario = auth.authenticate(request, username=username, password=password)
#Se os dados são coesos, o login é realizado com a authenticação
if usuario is not None:
auth.login(request, usuario)
messages.success(request, 'Foi logado com sucesso!')
return redirect('lista_livros')
else:
messages.error(request, 'Erro ao efetuar login')
return render(request, 'livro_detalhes.html', {'login_form' : login_form})
Exemplo:
logout_view:
def logout_view(request):
auth.logout(request)
messages.success(request, 'Logout efetuado com sucesso!')
# Redirecione para a página desejada após o logout.
return redirect('detalhes')
Exemplo:
🔔 # Para criar um modal de login com os requisitos mencionados, você pode usar o Bootstrap para estilizar o modal e o próprio Django para criar o formulário de login. Aqui estão as etapas para criar esse modal:
-
Certifique-se de que você tenha a biblioteca Bootstrap incluída em seu projeto. Você pode obtê-lo via CDN ou instalá-lo localmente aqui Bootstrap v5.3.2.
-
Exemplo Bootstrap vai CDN:
- Exemplo Bootstrap arquivos externos (collectstatic):
🔩 - Lembrando que depois de baixar os arquivos externos, você deve coloca-los dentro do
setup/static
em suas respectivas pastas,CSS
eJS
, logo depois utilizar o comandopython ./manage.py collectstatic
novamente.
🔔 # Nesse exemplo iremos criar o Modal de Login, em um Partials, e iremos usar o
include
em todas as páginas que tiver o navbar com botão de Login.
- Crie um arquivo HTML chamado Modal em
templates/partials/
, pastas essas localizadas dentro do seu aplicativo:
- Insere esses códigos dentro do arquivo HTML:
{% load static %}
<!-- Modal de Login -->
<div class="modal fade" id="modalLogin" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Login</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<!-- Formulário de Login -->
<form method="post">
{% csrf_token %}
{{ form.username.label_tag }}
{{ form.username }}
{{ form.password.label_tag }}
{{ form.password }}
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancelar</button>
<button type="submit" class="btn btn-primary">Entrar</button>
</div>
</div>
</div>
</div>
- Agora no arquivo
header.html
, vamos estar inserindo oinclude
, dessa forma automaticamente todas as páginas que conterem o include do Header, vão receber o do Modal.
{% include 'partials/modal.html' %}
- Vá até o diretório templates/partials e crie o arquivo chamado alerts.html com esses códigos aqui:
{% if messages %}
{% for message in messages %}
<div class = "alert alert-{{ message.tags }}">
{{message}}
</div>
<br>
{% endfor %}
{% endif %}
- Agora insira seu include em cada página de html, abaixo do navbar:
🔔 # Agora precisamos criar o nome referencial e a variável onde são armazenadas os campos criadas em
LoginForm
de dentro do seu arquivoforms.py
para dentro doviews.py
, então vamos até as Views de suas páginas html.
- Insere esse codigo atualizado na sua view de páginas.
- Ao final de configurar todos os códigos, você poderá testar o login no site usando o username que você criou e a senha que você utilizou do Superuser.
🔔 # Percebam que o CRUD é uma abreviação de Create, Read, Update e Delete, percebam também que já criamos 2 deles, que é o Create (Adicionar Livros) e o Read (Listar Livros), agora falta criarmos o Update e o Delete dos livros.
- Vá até o seu arquivo de views.py e crie as seguintes views:
delete:
def delete(request,id):
livros = Livro.objects.get(pk=id)
livros.delete()
messages.error(request, 'Livro deletado com sucesso!')
return redirect('lista_livros')
update:
def update(request, id):
livro = Livro.objects.get(pk=id)
if request.method == 'POST':
livro_form = LivroForm(request.POST, request.FILES, instance=livro)
if livro_form.is_valid():
livro_form.save()
messages.success(request, 'Livro editado com sucesso!')
return redirect('lista_livros')
else:
livro_form = LivroForm(instance=livro)
return render(request, 'editar_livros.html', {'livros': livro, 'livro_form': livro_form})
- Agora vá até seu arquivo de Website/urls.py para criar as seguintes urls.
- def update(request, id): livros = Livros.objects.get(pk=id): Nesse (request, id) ele seleciona o livro pelo id que estiver em seu item, seja através do card / botão / forms, já o get(pk=id)
(pk é uma abreviação para chave primária / "Primary Key")
procura pelo mesmo item que tiver o ID idêntico através do banco de dados do Livros para poder utiliza-lo.- instance=livros: Este parâmetro está vinculando o formulário a uma instância específica do modelo Livros (o livro que foi recuperado do banco de dados na linha anterior). Isso é crucial para que o formulário saiba qual livro está sendo atualizado.
- delete(): É uma função do Django especificamente para deletar itens do banco de dados, assim como o save() é uma função para salvar ou atualizar os dados do banco.
🔔 # Para editar os livros é necessário que exista uma página/modal que apresente um formulário para que seja preenchido e dessa forma, editar os livros que foram pegos pelo ID.
- Vá até ao seu diretório Website/templates e crie um HTML chamado
editar_livros.html
- Dentro do mesmo html, iremos inserir os códigos do extends, load static (para adquirir as personalizações externas) e o formulário para ser editado seus valores.
{% extends 'base.html' %}
{% load static %}
{% block content %}
<title>{% block title %}Adicionar Livro{% endblock %}</title>
<!--Header-->
{% include 'partials/header.html' %}
<!--Mensagens-->
{% include 'partials/alerts.html' %}
<main>
<h1>Adicionar Livro</h1>
<form method="post" enctype="multipart/form-data" action="{% url 'update' livros.id %}">
{% csrf_token %}
<div class="form-group">
<label for="{{ livro_form.titulo.id_for_label }}">Título:</label>
{{ livro_form.titulo }}
</div>
<div class="form-group">
<label for="{{ livro_form.autor.id_for_label }}">Autor:</label>
{{ livro_form.autor }}
</div>
<div class="form-group">
<label for="{{ livro_form.publicação.id_for_label }}">Data de Publicação:</label>
{{ livro_form.publicação }}
</div>
<div class="form-group">
<label for="{{ livro_form.paginas.id_for_label }}">Número de Páginas:</label>
{{ livro_form.paginas }}
</div>
<div class="form-group">
<label for="{{ livro_form.capa.id_for_label }}">Capa do Livro:</label>
{{ livro_form.capa }}
</div>
<button type="submit">Editar Livro</button>
</form>
</main>
<!--Footer-->
{% include 'partials/footer.html' %}
{% endblock %}
- Vamos agora criar a sua url no arquivo Website/urls.py e sua view no arquivo Website/views.py
views.py:
def editar_livro(request, id):
livros = Livro.objects.get(pk=id)
livro_form = LivroForm(instance=livros)
return render(request, "editar_livros.html",{'livros':livros, 'livro_form':livro_form})
🔔 # Agora que já temos a página pronta e as funções, precisamos de interliga-las em botões para que seu sistema saiba qual item/livro ele irá adquirir o id para edita-lo ou deleta-lo
- Vá até a página de listar_livros.html e insira esses botões dentro do seu for para que seja identificado seus IDs.
{% extends 'base.html' %}
{% load static %}
{% block content %}
<title>{% block title %}Lista de Livros{% endblock %}</title>
<!--Header-->
{% include 'partials/header.html' %}
<!--Mensagens-->
{% include 'partials/alerts.html' %}
<!--Main-->
<main class="bg-gray">
<h1>Lista de Livros</h1>
<ul>
{% for livro in livros %}
<li>{{ livro.titulo }} por {{ livro.autor }}</li>
<li>
{% if livro.capa %}
<img src="{{ livro.capa.url }}" alt="capa-de-livros" width="10%">
{% else %}
<p>Capa não encontrada</p>
{% endif %}
</li>
<a href="{% url 'delete' livro.id %}"><button>Deletar</button></a>
<a href="{% url 'editar_livro' livro.id %}"><button>Editar</button></a>
{% endfor %}
</ul>
</main>
<!--Footer-->
{% include 'partials/footer.html' %}
{% endblock %}
Como consegue ver, adicionamos 2
<a>
com 2<button>
que possuem funções diferentes, um para deletar e outro para enviar até a página de edição onde será realizado o preenchimento do formulário.
🔔 # A fase de testes e depuração é crucial para garantir que seu aplicativo funcione corretamente e para detectar e corrigir quaisquer erros. Vamos começar com alguns conceitos básicos.
- Verifique se dentro do seu diretório de aplicativo (Website) possui um arquivo chamado tests.py, se não tiver, crie.
- Dentro deste arquivo é onde você irá escrever seus testes. Importe os módulos necessários no topo do arquivo.
from django.test import TestCase, Client
from .models import Livro
from django.urls import reverse
- Crie uma class de teste no seu arquivo tests.py
class LivroTest(TestCase):
def setUp(self):
# Configurações iniciais para os testes
Livro.objects.create(titulo="Meu Livro", autor="Autor Teste", publicação="2023-04-10", paginas=200)
def test_titulo_do_livro(self):
livro = Livro.objects.get(id=1)
self.assertEqual(livro.titulo, "Meu Livro")
- class LivroTest(TestCase): Aqui, você está criando uma classe de teste chamada
LivroTest
que herda dedjango.test.TestCase
. A classeTestCase
fornece métodos e funcionalidades específicos para testes em Django.- def setUp(self): Este é um método especial que é executado antes de cada teste. Nele, você configura as condições iniciais necessárias para seus testes. No seu caso, você está criando um objeto Livro no banco de dados com alguns dados fictícios.
- Livro.objects.create(titulo="Meu Livro", autor="Autor Teste", publicação="2023-04-10", paginas=200): Isso cria um objeto Livro no banco de dados com os valores fornecidos.
- def test_titulo_do_livro(self): Este é um método de teste específico. Métodos de teste devem começar com a palavra
test_
. Aqui, você está testando se o título do livro criado é igual a"Meu Livro"
.- livro = Livro.objects.get(id=1): Isso recupera o objeto
Livro
do banco de dados com o ID igual a 1.- self.assertEqual(livro.titulo, "Meu Livro"):
self.assertEqual
é um método deassert
fornecido pelo DjangoTestCase
. Ele verifica se o valor delivro.titulo
é igual a"Meu Livro"
. Se não for, o teste falhará.- self: Em Python,
self
é uma convenção para se referir à instância atual da classe. Neste contexto,self
é usado para acessar métodos e atributos da instância da classe de teste, bem como para chamar os métodos deassert
, comoself.assertEqual
.
- No terminal do diretório de seu projeto (WebBooks) vamos escrever o seguinte comando para realizar os testes de seu app
python manage.py test Website
- O teste deu como resultado "OK" pois está funcionando, podemos ver o tempo para a realização do teste e também a quantidade de tests que foram encontrados para serem realizados.
- 🎨 # OBS: Durante os testes, o Django cria um banco de dados separado para os testes e popula com os dados necessários para executar os testes e quando ele finaliza o teste, ele destrói tal banco (
default
) separado. Isso garante que seus testes não afetem seus dados de produção.
- Crie uma classe de teste de view
class LivroViewsTest(TestCase):
def setUp(self):
# Configurações iniciais para os testes
self.client = Client()
self.livro = Livro.objects.create(
titulo="Livro de Teste",
autor="Autor Teste",
publicação="2023-04-10",
paginas=200
)
def test_lista_livros_view(self):
# Testa se a view retorna um código de resposta 200 (OK)
response = self.client.get(reverse('lista_livros'))
self.assertEqual(response.status_code, 200)
# Testa se o template correto é usado
self.assertTemplateUsed(response, 'lista_livros.html')
# Testa se o livro criado está presente na página
self.assertContains(response, self.livro.titulo)
# Adicione mais testes conforme necessário
- self.client: Um cliente Django que pode ser usado para realizar solicitações HTTP simuladas durante os testes.
- self.client.get(reverse('lista_livros')): Aqui, você está fazendo uma solicitação
GET
para aURL
associada à viewlista_livros
.- self.assertEqual(response.status_code, 200): Verifica se a resposta tem um código de status
200
, indicando que a solicitação foi bem-sucedida.- self.assertTemplateUsed(response, 'lista_livros.html'): Verifica se o template
'lista_livros.html'
é usado para renderizar a resposta.- self.assertContains(response, self.livro.titulo): Verifica se o
título
dolivro
criado está presente na página.
- Execute o teste novamente no terminal
python manage.py test Website
Tudo Ok
- Vamos criar testes para algumas das funcionalidades do aplicativo. Vamos criar exemplos de testes para as views
lista_livros
,adicionar_livro
,editar_livro
,delete
,update
,login_view
, elogout_view
ainda no arquivo tests.py.
from django.test import TestCase, Client
from django.urls import reverse
from .models import Livro
from django.contrib.auth.models import User
class LivroViewsTest(TestCase):
def setUp(self):
# Configurações iniciais para os testes
self.client = Client()
self.user = User.objects.create_user(username='testuser', password='testpassword')
self.livro = Livro.objects.create(
titulo="Livro de Teste",
autor="Autor Teste",
capa="path/to/image.jpg",
publicação="2023-04-10",
paginas=200
)
def test_lista_livros_view(self):
# Testa se a view retorna um código de resposta 200 (OK)
response = self.client.get(reverse('lista_livros'))
self.assertEqual(response.status_code, 200)
# Testa se o template correto é usado
self.assertTemplateUsed(response, 'lista_livros.html')
# Testa se o livro criado está presente na página
self.assertContains(response, self.livro.titulo)
# Adicione mais testes conforme necessário
def test_adicionar_livro_view(self):
# Loga o usuário
self.client.login(username='testuser', password='testpassword')
# Testa se a view retorna um código de resposta 200 (OK)
response = self.client.get(reverse('adicionar_livro'))
self.assertEqual(response.status_code, 200)
# Testa se o template correto é usado
self.assertTemplateUsed(response, 'adicionar_livro.html')
# Adicione mais testes conforme necessário
def test_editar_livro_view(self):
# Loga o usuário
self.client.login(username='testuser', password='testpassword')
# Testa se a view retorna um código de resposta 200 (OK)
response = self.client.get(reverse('editar_livro', args=[self.livro.id]))
self.assertEqual(response.status_code, 200)
# Testa se o template correto é usado
self.assertTemplateUsed(response, 'editar_livros.html')
# Adicione mais testes conforme necessário
# Adicione mais testes para as outras views conforme necessário
def test_login_view(self):
# Testa se a view retorna um código de resposta 200 (OK)
response = self.client.get(reverse('login_user'))
self.assertEqual(response.status_code, 200)
# Testa se o template correto é usado
self.assertTemplateUsed(response, 'livro_detalhes.html')
# Adicione mais testes conforme necessário
def test_logout_view(self):
# Loga o usuário
self.client.login(username='testuser', password='testpassword')
# Testa se a view redireciona corretamente
response = self.client.get(reverse('logout_user'))
self.assertEqual(response.status_code, 302)
self.assertRedirects(response, reverse('livro_detalhes'))
# Adicione mais testes conforme necessário
def test_delete_view(self):
# Loga o usuário
self.client.login(username='testuser', password='testpassword')
# Testa se a view redireciona corretamente após excluir um livro
response = self.client.get(reverse('delete', args=[self.livro.id]))
self.assertEqual(response.status_code, 302)
self.assertRedirects(response, reverse('lista_livros'))
# Adicione mais testes conforme necessário
def test_update_view(self):
# Loga o usuário
self.client.login(username='testuser', password='testpassword')
# Testa se a view redireciona corretamente após editar um livro
response = self.client.get(reverse('update', args=[self.livro.id]))
self.assertEqual(response.status_code, 302)
self.assertRedirects(response, reverse('lista_livros'))
# Adicione mais testes conforme necessário
- Você pode ler mais sobre os testes de Django na sua documentação, ou apenas clicando em Django Tests
- Vamos adicionar o Django Debug Toolbar para ajudar na depuração.
Instale o Django Debug Toolbar pelo terminal:
pip install django-debug-toolbar
- Agora adicione o seguinte código no seu arquivo Website/urls.py e vá inserido conforme é pedido:
if DEBUG:
from django.conf import settings
import debug_toolbar
urlpatterns = [
path('__debug__/', include(debug_toolbar.urls)),
# ... suas outras urlpatterns ...
]
# Configuração para a barra de ferramentas
settings.INSTALLED_APPS += ['debug_toolbar']
settings.MIDDLEWARE += ['debug_toolbar.middleware.DebugToolbarMiddleware']
settings.DEBUG_TOOLBAR_CONFIG = {'SHOW_TOOLBAR_CALLBACK': lambda request: DEBUG}
Agora você pode usar a barra de ferramentas para depurar sua aplicação durante o desenvolvimento. Caso queira conhecer mais sobre Debugs e Toolbar do Django, recomendo que acessem as documentações de Django Debugging e Django Debug Toolbar
Lembre-se:
- Remova Pontos de Interrupção após a Depuração: Não esqueça de remover os pontos de interrupção adicionados com
pdb
quando terminar de depurar o código.- Não Use em Produção: Ferramentas de depuração podem ser uma ameaça à segurança e não devem ser usadas em ambientes de produção.
- Aprenda a Usar as Ferramentas de Depuração do seu Ambiente de Desenvolvimento: As IDEs modernas fornecem ótimas ferramentas de depuração.
🔔 # A fase de Deploy é a finalização do produto e implantação do projeto, podem ser usado métodos pagos ou assinaturas como da Hostinger ou Azure, existem várias formas de realizar o deploy do seu trabalho, mas isso não será abordado aqui na página