Lançamento Django 6.0: as novidades que todo dev precisa ver AGORA

Published on: 2025-12-03
Post image
pt django-60 lancamento-django novidades-django background-tasks csp-nativo seguranca-web python-314 atualizacao-django framework-django template-partials

Natalia Bidart anunciou em 3 de dezembro de 2025 o lançamento oficial do Django 6.0. A nova versão marca uma grande atualização do framework, misturando ferramentas modernas, foco em segurança e ajustes importantes de compatibilidade.

O pacote já está disponível na página de downloads do Django e no Python Package Index (PyPI). O lançamento foi assinado com a chave PGP de Natalia Bidart: 2EE82A8D9470983E.

Com essa versão, o Django 5.2 encerra o suporte principal. A última correção de bugs menores, a versão 5.2.9, saiu ontem. A linha 5.2 ainda receberá correções de segurança e de perda de dados até abril de 2028, e os usuários são orientados a atualizar antes disso para manter as correções de segurança em dia.

Já o Django 5.1 chegou ao fim do suporte estendido. A última atualização de segurança, 5.1.15, foi lançada em 2 de dezembro de 2025. Quem ainda está na série 5.1 é incentivado a migrar para uma versão suportada.

Os detalhes sobre versões ativas e calendário de lançamentos futuros continuam disponíveis na página de downloads do Django.

Compatibilidade com Python: adeus versões antigas 🐍

O Django 6.0 funciona com Python 3.12, 3.13 e 3.14, com suporte oficial apenas para o lançamento mais recente de cada série.

A linha Django 5.2.x foi a última a funcionar com Python 3.10 e 3.11. Isso também afeta dependências opcionais: todas agora precisam ser compatíveis com Python 3.12 ou superior, com versões mínimas recomendadas como:

  • aiosmtpd 1.4.5
  • argon2-cffi 23.1.0
  • bcrypt 4.1.1
  • docutils 0.22
  • geoip2 4.8.0
  • Pillow 10.1.0
  • mysqlclient 2.2.1
  • numpy 1.26.0
  • PyYAML 6.0.2
  • psycopg 3.1.12
  • psycopg2 2.9.9
  • redis-py 5.1.0
  • selenium 4.23.0
  • sqlparse 0.5.0
  • tblib 3.0.0

Depois do lançamento do Django 6.0, a recomendação para autores de apps de terceiros é abandonar o suporte a versões anteriores à 5.2 e rodar os testes com python -Wd, corrigindo todos os avisos de descontinuação antes de dar suporte formal ao 6.0.

Segurança: CSP nativo na caixa 🔐

Uma das grandes novidades é o suporte nativo a Content Security Policy (CSP), para reforçar a proteção contra injeção de conteúdo, como ataques de XSS.

Agora é possível declarar, diretamente no framework, quais origens de scripts, estilos, imagens e outros recursos são confiáveis. A integração vem com:

  • ContentSecurityPolicyMiddleware para adicionar os cabeçalhos de CSP;
  • o context processor csp() para gerar nonces;
  • configuração via SECURE_CSP e SECURE_CSP_REPORT_ONLY, recebendo dicionários Python.

As configurações podem usar constantes do módulo django.utils.csp.CSP, por exemplo:

from django.utils.csp import CSP

SECURE_CSP = {
"default-src": [CSP.SELF],
"script-src": [CSP.SELF, CSP.NONCE],
"img-src": [CSP.SELF, "https:"],
}

Isso gera um cabeçalho Content-Security-Policy como:

default-src 'self'; script-src 'self' 'nonce-SECRET'; img-src 'self' https:

O framework ainda oferece documentação específica: guia de “como fazer” com CSP, visão geral de segurança e referência com detalhes, inclusive sobre decoradores para sobrescrever ou desativar políticas em views individuais.

Template Partials: fragmentos reutilizáveis em templates 🧩

A linguagem de templates do Django ganhou suporte a template partials, permitindo criar pequenos blocos nomeados dentro de um mesmo arquivo para reaproveitar código sem precisar quebrar tudo em vários templates.

Dois novos tags entram em cena:

  • {% partialdef %} para definir o partial;
  • {% partial %} para renderizar o partial.

Além disso, partials podem ser referenciados com a sintaxe template_name#partial_name em get_template(), render(), {% include %} e outras APIs de carregamento de templates.

Quem já usava o pacote de terceiros django-template-partials conta com um guia de migração específico para se adaptar ao recurso agora integrado ao core.

Tarefas em segundo plano: novo framework de Tasks ⚙️

Outra mudança pesada é a introdução de um framework nativo de Background Tasks, pensado para rodar código fora do ciclo tradicional requisição–resposta HTTP.

Com ele, dá para descarregar trabalhos como envio de e-mails ou processamento de dados para workers em segundo plano. O sistema cuida de:

  • definição e validação de tarefas;
  • enfileiramento;
  • tratamento de resultados.

A definição de tarefas é feita com o decorador @task, por exemplo:

from django.core.mail import send_mail
from django.tasks import task

@task
def email_users(emails, subject, message):
return send_mail(subject, message, None, emails)

Depois disso, a tarefa pode ser enfileirada por um backend configurado:

email_users.enqueue(
emails=["user@example.com"],
subject="You have a message",
message="Hello there!",
)

Os backends são definidos via configuração TASKS. Duas opções já vêm incluídas, voltadas principalmente para desenvolvimento e testes.

Importante: o Django gerencia criação e enfileiramento das tarefas, mas não fornece o mecanismo de execução. A responsabilidade de rodar os jobs continua sendo de processos ou serviços externos.

A documentação traz uma visão geral do framework de Tasks e uma referência com os detalhes da API.

E-mail: adoção total da API moderna do Python 📧

O sistema de e-mail do Django foi atualizado para usar a API moderna introduzida no Python 3.6, baseada na classe email.message.EmailMessage.

Essa nova base:

  • oferece uma interface mais limpa e amigável a Unicode;
  • substitui o uso da API antiga (Compat32) e das classes de baixo nível de email.mime;
  • simplifica a composição e o envio de mensagens.

Uma mudança concreta é o retorno de EmailMessage.message(), que agora passa a ser uma instância de email.message.EmailMessage. Ela mantém a mesma API esperada por quem usava SafeMIMEText e SafeMIMEMultipart, mas já não é mais instância dessas classes, que foram marcadas como obsoletas.

Outros ajustes incluem:

  • novo argumento policy em EmailMessage.message(), permitindo escolher a política de e-mail (regra de atualização e serialização da mensagem), com padrão email.policy.default;
  • EmailMessage.attach() agora aceita objetos MIMEPart da API moderna;
  • vários detalhes internos foram reescritos, então subclasses personalizadas que mexem em métodos internos não documentados precisam ser revisadas.

Algumas propriedades não documentadas foram descartadas:

  • mixed_subtype e alternative_subtype em EmailMessage e EmailMultiAlternatives;
  • uso da propriedade encoding com objetos email.charset.Charset legados.

E, olhando para o futuro, vários comportamentos antigos já foram declarados como obsoletos. Por exemplo:

  • APIs em django.core.mail passam a exigir uso de keyword arguments para parâmetros opcionais em get_connection(), mail_admins(), mail_managers(), send_mail() e send_mass_mail();
  • ao criar EmailMessage ou EmailMultiAlternatives, apenas os quatro primeiros argumentos (subject, body, from_email, to) continuam aceitando forma posicional; o resto deve ser nomeado;
  • passar objetos MIMEBase da API legada para EmailMessage.attach() foi marcado como descontinuado;
  • a exceção django.core.mail.BadHeaderError foi deprecada em favor de ValueError, levantado pela API moderna;
  • as classes SafeMIMEText e SafeMIMEMultipart entram na lista de APIs obsoletas, assim como as funções não documentadas forbid_multi_line_headers() e message.sanitize_address().

Admin, autenticação, GIS, Postgres, staticfiles e mais: os extras do 6.0

django.contrib.admin

  • As ícones do admin agora usam o pacote Font Awesome Free na versão 6.7.2.
  • Um novo atributo AdminSite.password_change_form permite customizar o formulário de troca de senha no admin.
  • Níveis de mensagem messages.DEBUG e messages.INFO ganharam ícones e estilos CSS distintos. Antes, ambos pareciam com messages.SUCCESS. Como ModelAdmin.message_user() usa messages.INFO por padrão, quem quiser manter o visual antigo deve trocar o nível para messages.SUCCESS.

django.contrib.auth

  • O número padrão de iterações do hasher de senha PBKDF2 sobe de 1.000.000 para 1.200.000, fortalecendo o hashing.

django.contrib.gis

  • Nova propriedade GEOSGeometry.hasm para checar se a geometria possui dimensão M.
  • Função de banco Rotate, para rotacionar geometrias por um ângulo, em torno da origem ou de um ponto específico.
  • Atributo BaseGeometryWidget.base_layer para definir a camada base do mapa via JavaScript, permitindo personalizar provedores de tiles.
  • Novos recursos suportados no MariaDB 12.0.1+: lookups coveredby e isvalid, agregação Collect e funções GeoHash e IsValid.
  • Lookup geom_type e função de banco GeometryType() para filtrar geometrias por tipo.
  • Widgets em django.contrib.gis.forms.widgets passam a renderizar sem JavaScript inline; customizações de widgets ou templates podem precisar de ajuste para acompanhar o novo layout.

django.contrib.postgres

  • Novo tipo de expressão Lexeme para full text search, com:
    • escape automático do input;
    • operadores lógicos &, |, ~;
    • suporte a prefixo;
    • peso de termos.
  • Campos de modelo, índices e constraints do pacote passam a incluir system checks para garantir que django.contrib.postgres está instalado em INSTALLED_APPS.
  • As operações CreateExtension, BloomExtension, BtreeGinExtension, BtreeGistExtension, CITextExtension, CryptoExtension, HStoreExtension, TrigramExtension e UnaccentExtension passam a aceitar um parâmetro opcional hints, para ajudar roteadores de banco a tomar decisões.

django.contrib.staticfiles

  • ManifestStaticFilesStorage agora garante uma ordenação consistente dos caminhos no arquivo de manifesto, o que reduz diffs desnecessários.
  • O comando collectstatic passa a mostrar apenas um resumo de arquivos ignorados (e dos deletados com --clear) quando --verbosity 1. Para ver detalhes por arquivo, é preciso aumentar o nível para 2 ou mais.

Internacionalização

  • O framework ganhou suporte e traduções para o idioma crioulo haitiano.

Management commands

  • Os comandos startproject e startapp agora criam o diretório alvo customizado, se ele ainda não existir.
  • Utilitários comuns, como django.conf.settings, passam a ser importados automaticamente no shell por padrão.

Migrations

  • Migrations “espremidas” (squashed) podem ser novamente “espremidas” antes de virarem migrations normais.
  • Migrations passam a serializar instâncias de zoneinfo.ZoneInfo.
  • A serialização de objetos deconstructible agora suporta argumentos nomeados cujos nomes não são identificadores Python válidos.

Models e ORM

  • Constraints agora implementam um método check() já registrado no framework de checks.
  • O novo argumento order_by em Aggregate permite definir a ordenação dos elementos no resultado.
  • Um novo atributo de classe Aggregate.allow_order_by controla se a função de agregação aceita o argumento order_by.
  • A nova agregação StringAgg concatena valores em uma string, separados por um delimitador. Antes, ela existia apenas para PostgreSQL; agora é geral.
  • O método save() passa a lançar uma exceção especializada Model.NotUpdated quando um forced update não afeta nenhuma linha, em vez de um django.db.DatabaseError genérico.
  • QuerySet.raw() agora aceita modelos com CompositePrimaryKey.
  • Subqueries que retornam CompositePrimaryKey podem ser usadas em lookups além de __in, como __exact.
  • JSONField agora suporta indexação negativa de arrays no SQLite.
  • A nova agregação AnyValue retorna um valor arbitrário entre os não nulos, com suporte em SQLite, MySQL, Oracle e PostgreSQL 16+.
  • GeneratedFields e campos com expressões passam a ser atualizados a partir do banco após save() em backends com suporte a RETURNING (SQLite, PostgreSQL, Oracle). Em MySQL e MariaDB, os campos são marcados como deferred para forçar um refresh no acesso posterior.
  • O uso de ForeignObject com múltiplos from_fields em índices, constraints ou unique_together agora emite um system check de erro.

Paginação assíncrona

  • Entram em cena o AsyncPaginator e o AsyncPage, versões assíncronas de Paginator e Page.

Requests e responses

  • Ao rodar com ASGI, o framework agora suporta múltiplos cabeçalhos Cookie em requisições HTTP/2.

Templates

  • A variável forloop.length fica disponível dentro do laço for nos templates.
  • A tag querystring passa a sempre prefixar o retorno com ?, facilitando a geração consistente de links.
  • A mesma tag agora aceita múltiplos argumentos posicionais, contanto que sejam mapeamentos, como QueryDict ou dict.

Tests

  • O DiscoverRunner passa a suportar testes paralelos em sistemas que usam o método de inicialização de multiprocessing forkserver.

Banco de dados: mudanças que podem quebrar backends de terceiros

Algumas alterações no backend de banco exigem atenção de quem mantém integrações personalizadas.

  • BaseDatabaseSchemaEditor e os backends PostgreSQL deixam de usar CASCADE ao remover colunas.
  • Os métodos DatabaseOperations.return_insert_columns() e DatabaseOperations.fetch_returned_insert_rows() foram renomeados para returning_columns() e fetch_returned_rows(), já que agora valem também para UPDATE ... RETURNING, não só para INSERT ... RETURNING.
  • O método DatabaseOperations.fetch_returned_insert_columns() foi removido. Já fetch_returned_rows(), que substitui fetch_returned_insert_rows(), passa a exigir cursor e returning_params, como fazia o método removido.
  • Backends que suportam UPDATE ... RETURNING podem ajustar DatabaseFeatures.can_return_rows_from_update = True.

Fim do suporte ao MariaDB 10.5

Com o término do suporte upstream em junho de 2025, o Django 6.0 passa a funcionar apenas com MariaDB 10.6+.

DEFAULT_AUTO_FIELD: BigAutoField vira o padrão

Desde o Django 3.2, o template padrão de startproject já incluía:

DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"

E o template de startapp vinha com:

default_auto_field = "django.db.models.BigAutoField"

Mas, por compatibilidade, o valor real padrão de DEFAULT_AUTO_FIELD ainda era django.db.models.AutoField. Agora, no Django 6.0, o default passa a ser oficialmente django.db.models.BigAutoField e essas linhas são removidas dos templates.

Desde o Django 3.2 o sistema já emitia o aviso models.W042 para projetos que não configuravam DEFAULT_AUTO_FIELD. Quem ainda ignora esse aviso e quer manter o comportamento antigo precisa declarar explicitamente:

DEFAULT_AUTO_FIELD = 'django.db.models.AutoField'

ou, em nível de app:

default_auto_field = 'django.db.models.AutoField'

Expressões customizadas no ORM: params agora precisam ser tuplas

Expressões e lookups personalizados que implementam as_sql() (e métodos auxiliares como process_lhs() e process_rhs()) antes podiam retornar a sequência de parâmetros como lista ou tupla. Para evitar problemas de interoperabilidade, o segundo elemento retornado por as_sql() agora deve ser obrigatoriamente uma tupla:

def as_sql(self, compiler, connection) -> tuple[str, tuple]: ...

Quem mantém código compatível com múltiplas versões de Django deve se certificar de que qualquer pré-processamento de parâmetros aceite tanto listas quanto tuplas, por exemplo:

params = (*lhs_params, *rhs_params)

Outras mudanças gerais

  • O serializador JSON agora escreve uma quebra de linha ao final da saída, mesmo sem indent.
  • A função não documentada django.utils.http.parse_header_parameters() foi refeita para usar email.message.Message internamente. Cabeçalhos com mais de 10.000 caracteres passam a gerar ValueError.
  • A versão mínima de asgiref sobe de 3.8.1 para 3.9.1.

Funcionalidades marcadas como obsoletas no 6.0

Alguns recursos entram oficialmente em fase de descontinuação, com avisos de deprecação e remoção planejada em versões futuras.

  • django.core.mail:
    • Uso de argumentos posicionais para parâmetros opcionais (a partir de fail_silently) em get_connection(), mail_admins(), mail_managers(), send_mail() e send_mass_mail() passa a emitir warnings e será proibido no futuro.
    • Em EmailMessage e EmailMultiAlternatives, todos os parâmetros devem ser passados como keyword, exceto os quatro primeiros, que continuam aceitando forma posicional ou nomeada.
    • Passar objetos MIMEBase legados para EmailMessage.attach() (ou na lista de attachments) entra na lista de usos obsoletos.
    • A exceção BadHeaderError, as classes SafeMIMEText e SafeMIMEMultipart e as funções não documentadas forbid_multi_line_headers() e message.sanitize_address() são oficialmente marcadas como deprecated.
  • Banco de dados e ORM:
    • BaseDatabaseCreation.create_test_db(serialize) é descontinuado; o recomendado é usar serialize_db_to_string().
    • A classe StringAgg específica de PostgreSQL entra em descontinuação em favor da StringAgg geral.
    • OrderableAggMixin para PostgreSQL é substituído pelo novo atributo order_by em Aggregate.
    • O uso de % em aliases de coluna ou anotações é considerado obsoleto.
  • URL e texto:
    • No Django 7.0, o protocolo padrão em urlize e urlizetrunc passará de http para https. Durante o ciclo 6.x, é possível antecipar esse comportamento com o setting transitório URLIZE_ASSUME_HTTPS = True, que por sua vez já está marcado como deprecado.
  • ADMINS e MANAGERS:
    • Configurar essas listas como tuplas (nome, endereço) entra em desuso. A recomendação é usar apenas strings de e-mail. Se o nome for necessário, o formato sugerido é "Name" <address> ou o uso de email.utils.formataddr().
  • Paginator:
    • Passar um valor para orphans maior ou igual a per_page em Paginator e AsyncPaginator passa a ser desaconselhado.

Funcionalidades removidas no 6.0

O Django 6.0 também limpa a casa, removendo recursos que já haviam cumprido o ciclo de deprecação em versões anteriores (5.0 e 5.1).

  • ORM e banco de dados:
    • Suporte a argumentos posicionais em BaseConstraint some.
    • BaseDatabaseOperations.field_cast_sql() é removido.
    • django.db.models.sql.datastructures.Join não recorre mais a get_joining_columns().
    • Métodos ForeignObject.get_joining_columns(), ForeignObjectRel.get_joining_columns() e ForeignObject.get_reverse_joining_columns() são retirados.
    • O método Prefetch.get_current_queryset() deixa de existir.
    • Métodos get_prefetch_queryset() em managers relacionados e descritores são removidos.
    • get_prefetcher() e prefetch_related_objects() não caem mais no fallback get_prefetch_queryset().
    • O argumento check em CheckConstraint é eliminado.
    • O atributo OS_OPEN_FLAGS de FileSystemStorage deixa de existir.
  • Formulários e templates:
    • Os renderizadores transitórios DjangoDivFormRenderer e Jinja2DivFormRenderer saem de cena.
    • Chamar format_html() sem args ou kwargs não é mais permitido.
    • O esquema padrão de forms.URLField muda de "http" para "https".
    • O setting transitório FORMS_URLFIELD_ASSUME_HTTPS é removido.
  • URL routing:
    • django.urls.register_converter() deixa de aceitar sobrescrever conversores já existentes.
  • Drivers e integrações:
    • Suporte ao driver cx_Oracle é retirado.
  • Modelos e API de alto nível:
    • Passar argumentos posicionais para Model.save() e Model.asave() não é mais suportado.
    • A alias ChoicesMeta para django.db.models.enums.ChoicesType é removida.
    • O método ModelAdmin.log_deletion() e LogEntryManager.log_action() saem da API.
    • O método get_cache_name() em FieldCacheMixin é eliminado.
  • GeoDjango:
    • O método django.contrib.gis.geoip2.GeoIP2.coords() é removido.
    • O método django.contrib.gis.geoip2.GeoIP2.open() é removido.
    • O setter de django.contrib.gis.gdal.OGRGeometry.coord_dim não existe mais.
  • Utils:
    • O módulo django.utils.itercompat e a função não documentada is_iterable() desaparecem.
  • Mail e headers:
    • O suporte ao uso de foi removido (já citado em banco de dados, mas impacta formatações relacionadas).

Um detalhe importante: recursos deprecatados no Django 5.0 e 5.1 que chegaram ao fim do ciclo agora estão oficialmente fora da base do 6.0. A recomendação é sempre conferir as seções “Features deprecated in 5.0” e “Features deprecated in 5.1” das notas de versão anteriores para ter o passo a passo completo de migração.

No geral, o Django 6.0 sinaliza um ciclo mais moderno: Python recente, segurança reforçada (com CSP), background tasks integradas, templates mais modulares e uma limpeza ampla na API, preparando o terreno para as próximas versões do framework. 🧱✨