# Django 6.0 em 2026: Chaves Primárias Compostas, Tarefas em Background e Perguntas de Entrevista > Django 6.0 em 2026: chaves primárias compostas, tarefas em background, template partials, middleware CSP nativo e perguntas de entrevista técnica. - Published: 2026-06-09 - Updated: 2026-06-09 - Author: SharpSkill - Tags: django, python, composite-primary-keys, background-tasks, csp - Reading time: 10 min --- O Django 6.0 representa a maior evolução do framework Python para desenvolvimento web desde o lançamento da versão 4.0. Liberada em 2026, essa versão entrega funcionalidades que a comunidade Django solicitava há anos: chaves primárias compostas nativas no ORM, um sistema embutido de tarefas em background sem dependências externas, template partials para reaproveitamento de trechos HTML e um middleware de Content Security Policy integrado ao framework. O resultado prático é uma redução significativa na quantidade de pacotes de terceiros necessários para colocar uma aplicação Django em produção, além de uma arquitetura mais enxuta e padronizada. > **Linha do tempo de versões do Django** > > O Django segue um ciclo de lançamento previsível: versões LTS (Long Term Support) a cada dois anos e versões intermediárias a cada oito meses. O Django 6.0 exige Python 3.12 ou superior. As chaves primárias compostas, que apareceram como funcionalidade estável no Django 5.2, estão completamente integradas ao ORM nesta versão. Já o sistema de tarefas em background e os template partials são novidades exclusivas do Django 6.0. ## Chaves primárias compostas com CompositePrimaryKey Bancos de dados relacionais utilizam chaves primárias compostas para identificar registros de forma única por meio da combinação de duas ou mais colunas. Até o Django 5.2, para modelar esse tipo de relação era necessário recorrer a alternativas como `unique_together` ou pacotes de terceiros. O campo `CompositePrimaryKey` resolve essa questão diretamente no ORM, eliminando a necessidade de um campo `id` autoincrementável em tabelas de junção. O cenário mais comum envolve tabelas intermediárias em que a combinação de duas chaves estrangeiras forma a identidade única do registro. O exemplo abaixo modela um sistema de inventário onde cada produto em cada depósito possui uma quantidade associada: ```python # models.py from django.db import models class Product(models.Model): name = models.CharField(max_length=100) sku = models.CharField(max_length=20, unique=True) class Warehouse(models.Model): code = models.CharField(max_length=10, primary_key=True) location = models.CharField(max_length=200) class Inventory(models.Model): pk = models.CompositePrimaryKey("product_id", "warehouse_id") product = models.ForeignKey(Product, on_delete=models.CASCADE) warehouse = models.ForeignKey(Warehouse, on_delete=models.CASCADE) quantity = models.PositiveIntegerField(default=0) last_restocked = models.DateTimeField(auto_now=True) ``` O campo `pk` recebe os nomes das colunas no banco de dados (e não os nomes dos campos do modelo Django). O framework gera uma constraint `PRIMARY KEY (product_id, warehouse_id)` diretamente no banco, garantindo unicidade sem precisar de um campo `id` artificial. ## Consultando chaves compostas no ORM A interação com o ORM continua com a mesma interface que qualquer desenvolvedor Django já conhece. A chave composta é representada como uma tupla Python, o que permite filtrar, criar e atribuir registros de maneira intuitiva: ```python # views.py from .models import Inventory, Product, Warehouse # Create records laptop = Product.objects.create(name="Laptop Pro", sku="LP-001") warehouse_a = Warehouse.objects.create(code="WH-A", location="Berlin") item = Inventory.objects.create( product=laptop, warehouse=warehouse_a, quantity=50 ) # Access the composite pk as a tuple print(item.pk) # (1, "WH-A") # Filter by composite pk result = Inventory.objects.filter(pk=(1, "WH-A")).first() # Assign a composite pk directly new_item = Inventory(pk=(2, "WH-B")) print(new_item.product_id) # 2 print(new_item.warehouse_id) # "WH-B" ``` Essa funcionalidade é especialmente valiosa para equipes que trabalham com schemas legados de banco de dados ou que estão migrando de outros ORMs que já ofereciam suporte a chaves compostas. O Django Admin, os serializers do Django REST Framework e o sistema de migrations reconhecem automaticamente modelos com `CompositePrimaryKey`, sem necessidade de nenhuma configuração adicional. ## Tarefas em background nativas com o decorator @task Uma das adições mais aguardadas do Django 6.0 é o sistema de tarefas em background integrado ao framework. O módulo `django.tasks` disponibiliza um decorator `@task` e um método `.enqueue()` que permitem adiar a execução de funções sem precisar configurar um broker de mensagens externo ou workers separados. O sistema foi projetado para operações que não devem travar o ciclo de request-response HTTP: envio de e-mails, geração de relatórios, processamento de uploads e chamadas a APIs externas. A definição de tarefas segue a convenção do Django de manter um módulo `tasks.py` dentro de cada app: ```python # tasks.py from django.tasks import task from django.core.mail import send_mail @task def send_welcome_email(user_email, username): """Send a welcome email after user registration.""" send_mail( subject="Welcome to the platform", message=f"Hello {username}, your account is ready.", from_email=None, # uses DEFAULT_FROM_EMAIL recipient_list=[user_email], ) return f"Email sent to {user_email}" @task def generate_report(report_id, format="pdf"): """Generate an export report asynchronously.""" from .services import ReportService report = ReportService.generate(report_id, format=format) return report.file_path ``` O disparo de tarefas a partir de uma view utiliza o método `.enqueue()`, que serializa os argumentos e os envia para o backend configurado para execução assíncrona: ```python # views.py from .tasks import send_welcome_email, generate_report def register_user(request): # ... user creation logic ... # Enqueue the task for background execution send_welcome_email.enqueue( user_email=user.email, username=user.username ) return redirect("dashboard") def export_view(request, report_id): generate_report.enqueue(report_id=report_id, format="csv") return JsonResponse({"status": "processing"}) ``` O Django 6.0 inclui um backend de banco de dados como opção padrão e um backend Redis para cenários com maior volume de tarefas. A configuração no `settings.py` permite escolher o backend e ajustar parâmetros como número de workers e intervalo de polling. A distinção de escopo é fundamental para tomar a decisão correta. As tarefas nativas do Django 6.0 atendem de forma eficiente casos de uso simples a moderados. Para cenários que exigem roteamento avançado de filas, workflows complexos (chains, chords), retentativas com backoff exponencial configurável ou processamento distribuído em várias máquinas, o [Celery continua sendo a ferramenta mais adequada](/pt/blog/django/django-celery-async-tasks-interview-2026). ## Template partials: fragmentos reutilizáveis no sistema de templates O sistema de templates do Django ganha uma funcionalidade que desenvolvedores acostumados com frameworks frontend já conhecem: a possibilidade de definir fragmentos reutilizáveis dentro de um mesmo arquivo e referenciá-los de forma seletiva. As tags `{% partialdef %}` e `{% partial %}` permitem agrupar vários componentes visuais em um único template e consumir apenas o fragmento desejado. O exemplo a seguir define duas representações de um produto -- um card para catálogo e uma linha para tabelas de inventário -- dentro do mesmo arquivo: ```html {% partialdef product_card %}
{{ product.price|floatformat:2 }} EUR
{% if product.in_stock %}In Stock{% else %}Sold Out{% endif %}