O Django 6.0 foi lançado em 3 de dezembro de 2025 com três novidades que a comunidade Python esperava há anos: um framework de tasks nativo, suporte a Content Security Policy sem bibliotecas externas e template partials para composição modular. Mas como acontece com toda release grande, o diabo mora nos detalhes.

Este post cobre o que cada feature faz na prática, com código que você pode copiar, e onde o Django 6.0 ainda deixa lacunas que ferramentas como Celery precisam preencher.

O que o Django 6.0 traz de novo

O Django 6.0 exige Python 3.12 ou superior (3.12, 3.13 e 3.14 são suportados). Se seu projeto ainda roda em Python 3.10 ou 3.11, a última versão compatível é o Django 5.2.x.

As três features de destaque são:

  • Um framework de tasks para execução de código fora do ciclo request-response
  • Suporte nativo a Content Security Policy (CSP) via middleware e settings
  • Template partials com as tags {% partialdef %} e {% partial %}

Além dessas, a release inclui um AsyncPaginator, modernização da API de email, forloop.length disponível em loops de template e a troca dos ícones do admin para Font Awesome 6.7.2. Mas as três primeiras são as que mudam o dia a dia.

Tasks: o framework de tarefas que não substitui o Celery

Essa é a feature mais esperada e a mais mal compreendida do Django 6.0. O DEP 0014 (Django Enhancement Proposal) propôs uma API padronizada para background tasks, inspirada na abordagem do Laravel. A ideia era acabar com a fragmentação: cada projeto Django escolhia entre Celery, django-rq, Huey ou outra solução, cada uma com sua própria API.

O resultado é um decorator @task e um método enqueue(). A API é limpa:

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

@task
def notificar_usuarios(emails, assunto, mensagem):
    return send_mail(assunto, mensagem, None, emails)

Para enfileirar a task:

notificar_usuarios.enqueue(
    emails=["usuario@exemplo.com"],
    assunto="Novo comentário",
    mensagem="Alguém respondeu seu post.",
)

A configuração fica no settings.py:

TASKS = {
    "default": {
        "BACKEND": "django.tasks.backends.immediate.ImmediateBackend"
    }
}

O Django 6.0 inclui dois backends no core:

  • ImmediateBackend executa a task na hora, bloqueando a request. Serve para desenvolvimento
  • DummyBackend guarda as tasks em memória sem executar. Útil em testes

Para produção, você precisa de um backend third-party. O mais direto é o pacote django-tasks de Jake Howard, que fornece um DatabaseBackend usando o ORM como fila. Mesmo com ele, você ainda precisa de um worker externo (python manage.py db_worker) para consumir a fila

O que falta

Aqui é onde a empolgação precisa de um banho de água fria. O framework de tasks do Django 6.0 não inclui:

  • Agendamento de tasks recorrentes (cron jobs)
  • Retries automáticos em caso de falha
  • Workers para processar a fila
  • Garantias de execução (at-least-once, exactly-once)

O Django cria e enfileira tasks. Quem executa é responsabilidade sua. Você precisa de um worker externo rodando em um processo separado para consumir a fila — seja via django-tasks ou outra implementação compatível.

Na prática, se seu projeto precisa de agendamento, retries ou monitoramento de tasks, o Celery continua sendo necessário. O framework nativo resolve bem o caso mais simples: disparar uma task fire-and-forget, como enviar um email após um cadastro. Para qualquer coisa além disso, ferramentas externas continuam no jogo.

O valor real dessa feature não é substituir o Celery. É criar um contrato de API compartilhado. Bibliotecas de tasks podem implementar o backend do Django em vez de inventar sua própria interface, e seu código não fica acoplado a uma implementação específica.

Content Security Policy nativo

O suporte a CSP é a feature mais pronta para produção das três. Antes do Django 6.0, a opção mais comum era o pacote django-csp. Agora o framework oferece isso nativamente.

A configuração usa dicionários Python com constantes do Django:

from django.utils.csp import CSP

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

Isso gera o header:

default-src 'self'; script-src 'self' 'nonce-abc123'; img-src 'self' https:; style-src 'self' 'nonce-abc123'

Para habilitar, adicione o middleware e o context processor:

MIDDLEWARE = [
    "django.middleware.csp.ContentSecurityPolicyMiddleware",
    # ... outros middlewares
]

TEMPLATES = [
    {
        "OPTIONS": {
            "context_processors": [
                "django.template.context_processors.csp",
                # ... outros context processors
            ],
        },
    },
]

Nos templates, use o nonce gerado automaticamente:

<script nonce="{{ csp_nonce }}">
  console.log("Script permitido pelo CSP");
</script>

O Django também suporta SECURE_CSP_REPORT_ONLY para monitorar violações sem bloquear recursos. Comece com report-only, analise os logs e só depois mude para enforcement. Tentar enforçar CSP de primeira em um projeto existente vai quebrar coisas.

Decorators por view permitem sobrescrever ou desabilitar a política em endpoints específicos. Isso é útil para páginas que carregam conteúdo de terceiros, como embeds de YouTube ou widgets de analytics.

Template partials e composição modular

Se você já usou htmx com Django, provavelmente conhece o pacote django-template-partials. O Django 6.0 absorveu essa ideia no core com duas tags novas: {% partialdef %} e {% partial %}.

O problema que elas resolvem: em projetos com htmx, é comum retornar apenas um fragmento de HTML em vez da página inteira. Antes, isso significava criar um arquivo de template separado para cada fragmento, mesmo que ele tivesse 5 linhas.

Agora você define o fragmento dentro do próprio template:

{% partialdef lista-comentarios %}
<ul>
  {% for comentario in comentarios %}
    <li>{{ comentario.texto }} — {{ comentario.autor }}</li>
  {% endfor %}
</ul>
{% endpartialdef %}

E renderiza o partial em qualquer lugar:

{% partial lista-comentarios %}

A parte que muda o jogo é a sintaxe de referência externa. Do lado da view, você pode renderizar apenas o partial sem carregar o template inteiro:

from django.template.loader import render_to_string

html = render_to_string("blog/post_detail.html#lista-comentarios", {
    "comentarios": comentarios,
})

A notação template_name#partial_name funciona com get_template(), render(), {% include %} e as demais ferramentas de carregamento de template. A adoção crescente do htmx na comunidade Django foi uma das forças que motivaram essa adição ao core.

Para projetos que já usam django-template-partials, o Django 6.0 inclui um guia de migração na documentação oficial.

O que mais mudou

Além das três features principais, o Django 6.0 traz mudanças menores que valem a atenção:

AsyncPaginator e AsyncPage são versões assíncronas do paginador padrão. Se sua view é async, agora a paginação não precisa de sync_to_async.

A API de email foi modernizada para usar email.message.EmailMessage do Python 3.6+, com suporte a Unicode nativo e interface mais limpa. O método message() agora aceita um argumento policy e permite anexar objetos MIMEPart diretamente.

forloop.length está disponível em loops {% for %}, retornando o total de itens na iteração. Parece pouco, mas elimina a necessidade de passar o count separadamente do queryset.

StringAgg agora funciona em todos os bancos suportados, não só no PostgreSQL. Projetos que usam MariaDB ou SQLite ganham essa agregação sem gambiarras.

O DEFAULT_AUTO_FIELD muda de AutoField para BigAutoField. Projetos existentes que não definiram esse setting explicitamente vão ver warnings na migração. Se seu projeto é antigo, defina DEFAULT_AUTO_FIELD = "django.db.models.AutoField" no settings para manter o comportamento anterior.

Conclusão

O Django 6.0 acertou no CSP nativo e nos template partials. As duas features estão prontas para produção e resolvem problemas reais sem ressalvas. O framework de tasks é a peça mais ambiciosa, mas chega incompleto: sem workers, sem retries, sem agendamento. O valor dele hoje é mais como contrato de API do que como solução pronta.

Se seu projeto roda Django 5.2, o upgrade vale pela CSP e pelos partials. Se a motivação principal é o tasks, avalie se o seu caso de uso cabe no modelo fire-and-forget. Para qualquer coisa mais complexa, o Celery continua no requirements.txt.

A próxima versão, Django 6.1, já está em desenvolvimento. A documentação oficial lista as release notes completas em docs.djangoproject.com.

Referências pesquisadas nesta publicação