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)

view_classe.py
from django.http import HttpResponse
from django.views import View

class HelloWorldView(View):
    def get(self, request):
        return HttpResponse("Olá, mundo!")
view_funcao.py
from django.http import HttpResponse

def hello_world(request):
    return HttpResponse("Olá, mundo!")
urls.py
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.

views.py
from django.views.generic import TemplateView

class SobreView(TemplateView):
    # Nome do template a ser renderizado
    template_name = "meu_app/sobre.html"
views_com_dados.py
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

urls.py
from django.urls import path
from .views import SobreView

urlpatterns = [
    path("sobre/", SobreView.as_view(), name="sobre"),
]
sobre.html
<!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

views_db.py
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
urls.py
from . import views
from django.urls import path

urlpatterns = [
    path("avaliacao/<int:id>", views.AvaliacaoDetailView.as_view()),
]
models.py
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
avaliacao_detalhe.html
{% 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.

urls_principal.py
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 TemplateViewListView 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

views.py
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.

urls.py
from django.urls import path
from . import views

urlpatterns = [
     path("avaliacoes", views.AvaliacaoListView.as_view()),
]
avaliacao_list.html
<!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

views.py
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.

urls.py
from django.urls import path
from . import views

urlpatterns = [
     path("reviews/<int:pk>", views.AvaliacaoDetailView.as_view()),
]
avaliacao_detalhe.html
{% 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

views.py
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

forms.py
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

views.py
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)

models.py
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
forms.py
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',
            }
        }