Classe de View (Class-Based View)
Usar uma Class-Based View ou CBV no Django, em vez de uma função (Function-Based View ou FBV), traz vantagens em termos de organização, reutilização e extensibilidade, especialmente para projetos grandes ou complexos. A principal diferença é que uma FBV é apenas uma função que manipula uma solicitação HTTP, enquanto uma CBV é uma classe que organiza a lógica em métodos como get, post, put, etc., correspondendo aos métodos HTTP. Herde a classe View, e por convenção colocamos View depois do nome da Classe.
O método as_view é um método de classe usada para transformar uma classe baseada em view (Class-Based View, ou CBV) em uma função que pode ser utilizada pelo sistema de roteamento de URLs do Django. as_view cria uma instância da classe view e retorna uma função que processa as requisições HTTP. Ele conecta os métodos HTTP da classe (get, post, etc.) ao tipo correspondente de requisição (GET, POST, etc.).
| Classe (CBV) vs Função (FBV)
from django.http import HttpResponse
from django.views import View
class HelloWorldView(View):
def get(self, request):
return HttpResponse("Olá, mundo!")
from django.http import HttpResponse
def hello_world(request):
return HttpResponse("Olá, mundo!")
from django.urls import path
from .views import HelloWorldView
urlpatterns = [
path('hello/', HelloWorldView.as_view(), name='hello_world'),
]
Assuntos Relacionados
TemplateView
TemplateView é uma classe baseada em view (Class-Based View, ou CBV) projetada para renderizar um template estático ou com um contexto mínimo. É ideal para páginas simples que não requerem lógica complexa no processamento de requisições, como páginas de "Sobre", "Contato" ou "Política de Privacidade". A TemplateView herda de View e facilita o uso de templates ao fornecer um comportamento padrão para lidar com requisições GET e renderizar um template automaticamente. Tem o método padrão get que já implementa um comportamento padrão para requisições GET.
| Exemplo TemplateViews
Use django.views.generic para importar TemplateView e outras CBVs principais. A importação de django.views.generic.base é possível, mas não necessária para o uso convencional de TemplateView.
from django.views.generic import TemplateView
class SobreView(TemplateView):
# Nome do template a ser renderizado
template_name = "meu_app/sobre.html"
from django.views.generic import TemplateView
class SobreView(TemplateView):
template_name = "sobre.html"
def get_context_data(self, **kwargs):
# Obtém o contexto padrão
context = super().get_context_data(**kwargs)
# Adiciona dados personalizados
context['titulo'] = "Página Sobre"
context['descricao'] = "Bem-vindo à nossa página estática."
return context
É possível passar dados adicionais ao template, sobrescrevendo o método get_context_data
from django.urls import path
from .views import SobreView
urlpatterns = [
path("sobre/", SobreView.as_view(), name="sobre"),
]
<!DOCTYPE html>
<html>
<head>
<title>Sobre</title>
</head>
<body>
<h1>Bem-vindo à página Sobre</h1>
<p>Esta é uma página estática com TemplateView!</p>
</body>
</html>
| Exemplo TemplateViews com Models
Este é apenas um exemplo poderia ser feito, mas por boa pratica não se teve usar TemplateView para exibir detalhes ou listas, para isso temos as classes DetailView e ListView
from django.views.generic import TemplateView
from .models import Avaliacao
class AvaliacaoDetailView(TemplateView):
template_name = "meu_app/avaliacao_detalhe.html"
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
# O id do kwargs vem da url dinâmica
avaliacao_id = kwargs['id']
avaliacao_selecionada = Avaliacao.objects.get(pk=avaliacao_id)
context['avaliacao'] = avaliacao_selecionada
return context
from . import views
from django.urls import path
urlpatterns = [
path("avaliacao/<int:id>", views.AvaliacaoDetailView.as_view()),
]
from django.db import models
class Avaliacao(models.Model):
nome_usuario = models.CharField(max_length=20)
descricao = models.TextField()
avaliacao = models.IntegerField()
def __str__(self):
return self.nome_usuario
{% extends "base.html" %}
{% block title %}Detalhes Avaliação{% endblock %}
{% block content %}
<h1>{{ avaliacao.nome_usuario }}</h1>
<p>Nota: {{ avaliacao.avaliacao }}</p>
<p>{{ avaliacao.descricao }}</p>
{% endblock %}
RedirectView
A RedirectView é uma classe genérica fornecida pelo Django que facilita a criação de visualizações que redirecionam para outra URL. Ela é útil quando você deseja criar um redirecionamento permanente ou temporário com o mínimo de configuração. Usada comumente quando o objetivo é apenas encaminhar o usuário para outra página ou site.
from django.contrib import admin
from django.urls import path, include
from django.views.generic.base import RedirectView
urlpatterns = [
path('admin/', admin.site.urls),
# redireciona o navegador para noticias (que é a url de baixo)
path('', RedirectView.as_view(url='/noticias'))
# pode ser acessado digitando http://localhost:8000/noticias ou apenas http://localhost:8000/
path('noticias/', include("noticias.urls"))
]
ListView
A ListView é uma Class-Based View (CBV) do Django projetada para exibir uma lista de objetos de um modelo ou outra fonte de dados. Ela simplifica o processo de renderização de listas ao fornecer ferramentas prontas para lidar com consultas, organização e exibição de dados. Diferente da TemplateView, ListView fornece funcionalidades específicas para lidar com listas de objetos, enquanto TemplateView é mais genérico e usado para páginas sem lógica de dados complexa.
Use o ListView quando for preciso exibir uma lista de objetos em uma página, como uma lista de produtos em um e-commerce, ou uma lista de postagens em um blog, ou um lista de usuários em um painel de administração e etc.
Ao selecionar um modelo o ListView já passa um objeto chamado object_list, com o resultado completo da busca no banco de dados, para você usar em seu template (por exemplo iterar sobre ele).
Segue uma tabela com os métodos mais importantes da ListView e suas funções:
| Método | Descrição | Exemplo |
|---|---|---|
get_queryset(self) |
Retorna o queryset que será utilizado para exibir os objetos. Pode ser personalizado para aplicar filtros ou ordenação. | def get_queryset(self): return Livro.objects.filter(autor="J.K. Rowling").order_by("publicacao") |
get_context_data(self, **kwargs) |
Permite adicionar informações extras ao contexto renderizado no template. | def get_context_data(self, **kwargs):<br> context = super().get_context_data(**kwargs) context['titulo'] = "Lista de Livros" return context |
get_template_names(self) |
Define o nome do template que será utilizado para renderizar a view. | def get_template_names(self): return ["livros/livro_list.html"] |
paginate_by (atributo) |
Define o número de objetos exibidos por página. | paginate_by = 10 |
get_paginate_by(self, queryset) |
Permite definir dinamicamente o número de itens por página. | def get_paginate_by(self, queryset): return 5 if self.request.user.is_authenticated else 10 |
get_ordering(self) |
Define a ordenação dos objetos exibidos. | def get_ordering(self): return "publicacao" |
allow_empty (atributo) |
Define se a view pode renderizar mesmo que o queryset esteja vazio. | allow_empty = True |
get_allow_empty(self) |
Permite controlar dinamicamente se a view deve renderizar com um queryset vazio. | def get_allow_empty(self): return self.request.user.is_staff |
get_context_object_name(self, object_list) |
Define o nome da variável usada no contexto do template para a lista de objetos. | def get_context_object_name(self, object_list): return "meus_livros" |
get_paginate_orphans(self) |
Define o número de objetos adicionais permitidos em uma página para evitar que uma página final tenha muito poucos objetos. | def get_paginate_orphans(self): return 2 |
| Exemplo ListView
from django.views.generic import ListView
class AvaliacaoListView(ListView):
template_name = "meu_app/avaliacao_list.html"
model = Avaliacao
context_object_name = "Avaliacoes"
# Número de itens por página
paginate_by = 10
# Esse código Substituiria um uso como esse:
class ReviewListView(TemplateView):
template_name = "reviews/review_list.html"
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
reviews = Review.objects.all()
context["reviews"] = reviews
return context
O django buscará automaticamente todos os dados do seu modelo e renderizará sua pagina com um objeto contendo essa lista chamada object_list, mas que pode ter seu nome sobrescrito no atributo context_object_name.
from django.urls import path
from . import views
urlpatterns = [
path("avaliacoes", views.AvaliacaoListView.as_view()),
]
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>All Reviews</title>
</head>
<body>
<h1>All Reviews</h1>
<ul>
{% for review in object_list %}
<li>{{ review.user_name }} (Rating: {{ review.rating }})</li>
{% endfor %}
</ul>
<div>
<ul class="pagination">
{% if page_obj.has_previous %}
<li><a href="?page=1">First</a></li>
<li><a href="?page={{ page_obj.previous_page_number }}">Previous</a></li>
{% else %}
<li>First</li>
<li>Previous</li>
{% endif %}
<li>Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}</li>
{% if page_obj.has_next %}
<li><a href="?page={{ page_obj.next_page_number }}">Next</a></li>
<li><a href="?page={{ page_obj.paginator.num_pages }}">Last</a></li>
{% else %}
<li>Next</li>
<li>Last</li>
{% endif %}
</ul>
</div>
</body>
</html>
DetailView
O DetailView é uma classe genérica de visualização fornecida pelo Django para exibir detalhes de um único objeto de um modelo. Ele é usado quando você quer mostrar informações detalhadas sobre um item específico no banco de dados, geralmente identificado por um identificador único, como um ID ou slug. Definimos a url como pk para que ele use essa chave primária para localizar o "pedaço" de código (ou busca simples de um resultado) que queremo exibir.
Ao selecionar um modelo o DetailView já passa um objeto chamado object (como contexto para página HTML), com o resultado único da busca no banco de dados. Caso o atributo context_object_name não for especificado em sua classe, o Django cria automaticamente um nome de contexto com base no nome do modelo associado. Definido com letra minuscula: Se o modelo for Avaliacao, o nome no contexto será Avaliacao. se for UserProfile, o nome será userprofile. etc...
Aqui está uma tabela com os principais métodos de DetailView no Django:
| Método | Descrição | Uso Comum |
|---|---|---|
get_object() |
Retorna o objeto que será exibido na DetailView. | Personalizar como o objeto é recuperado (ex.: filtro adicional no banco de dados). |
get_context_data(**kwargs) |
Adiciona dados personalizados ao contexto enviado para o template. | Adicionar variáveis extras ao contexto (ex.: dados relacionados ou informações calculadas). |
get_queryset() |
Define ou retorna o conjunto de objetos do qual o objeto detalhado será selecionado. | Alterar a consulta padrão para buscar o objeto (ex.: filtrar por critérios específicos). |
get_template_names() |
Define ou retorna o nome(s) do template que será renderizado. | Usar templates diferentes com base em alguma lógica. |
get_context_object_name() |
Define ou retorna o nome do objeto no contexto. | Personalizar o nome usado para acessar o objeto no template. |
| Exemplo DetailView
from django.views.generic import DetailView
from .models import Avaliacao
class AvaliacaoDetailView(DetailView):
template_name = "meu_app/avaliacao_detalhe.html"
model = Avaliacao
Uso a PK passada na url para buscar o resultado no modelo informado.
from django.urls import path
from . import views
urlpatterns = [
path("reviews/<int:pk>", views.AvaliacaoDetailView.as_view()),
]
{% extends "base.html" %}
{% block title %}Detalhes Avaliação{% endblock %}
{% block content %}
<!-- poderia usar object.nome_usuario como explicado na descrição do assunto -->
<h1>{{ avaliacao.nome_usuario }}</h1>
<p>Nota: {{ avaliacao.avaliacao }}</p>
<p>{{ avaliacao.descricao }}</p>
{% endblock %}
FormView
FormView é uma view genérica baseada em classe no Django usada para lidar com formulários. Ela fornece métodos e lógica padrão para processar e validar formulários, economizando tempo e esforço no desenvolvimento de aplicações que requerem interações baseadas em formulários. Renderiza um formulário automaticamente na página inicial (método GET).Valida e processa os dados do formulário quando enviados (método POST). Gerencia todo o ciclo de vida de um formulário: renderização, submissão, validação e redirecionamento após o sucesso.
| Exemplo FormView
from django.views.generic import FormView
from .forms import AvaliacaoForm
class AvaliacaoView(FormView):
# Informa o formulário
form_class = ReviewForm
# Informa o template a ser renderizado e processado
template_name = 'meu_app/avaliacao.html'
# Informa o redirecionamento em caso de formulário sem erros
success_url = '/sucesso'
# Recebe o formulário valido para tomar alguma ação (nesse caso salvar no banco de dados)
def form_valid(self, form):
form.save()
return super().form_valid(form)
Get e Post são processados automaticamente usando FormView
class AvaliacaoForm(forms.ModelForm):
class Meta:
model = Avaliacao
fields = "__all__"
labels = {
"nome_usuario ": "Seu Nome",
"descricao": "Feedback",
"Avaliacao": "Avaliação",
}
error_messages = {
"nome_usuario ": {
'required': 'Campo obrigatório',
'max_length': 'Máximo de 100 caracteres',
}
}
CreateView
CreateView é uma view genérica baseada em classe no Django, usada para criar novos objetos no banco de dados. Ela simplifica o processo de criação de registros ao lidar automaticamente com renderização de formulários baseados em modelos, validação dos dados do formulário, salvamento do objeto no banco de dados após a validação, redirecionamento para uma URL de sucesso.
Basicamente o CreateView Salvará automáticamente o formulário no banco de dados
| Exemplo CreateView
from django.views.generic import CreateView
from .models import Avaliacao
from .forms import AvaliacaoForm
class AvaliacaoView(CreateView):
# Informa o modelo para Criação dos dados
model = Avaliacao
form_class = AvaliacaoForm
template_name = 'meu_app/avaliacao.html'
success_url = '/sucesso'
# Define quais campos do modelo estarão no formulário
# fields = "__all__"
Não é necessário um formulário pois ela já cria com base no modelo. Mas você pode informar o formulário, se desejar algumas configurações mais especificas (caso do exemplo), como configurar os labels e as mensagens de erro (feito no formulário)
from django.db import models
class Avaliacao(models.Model):
nome_usuario = models.CharField(max_length=20)
descricao = models.TextField()
avaliacao = models.IntegerField()
def __str__(self):
return self.nome_usuario
from django import forms
from .models import Avaliacao
class AvaliacaoForm(forms.ModelForm):
class Meta:
model = Avaliacao
fields = "__all__"
labels = {
"nome_usuario ": "Seu Nome",
"descricao": "Feedback",
"Avaliacao": "Avaliação",
}
error_messages = {
"nome_usuario ": {
'required': 'Campo obrigatório',
'max_length': 'Máximo de 100 caracteres',
}
}