Django 6.0: Samengestelde Primaire Sleutels, Achtergrondtaken en Sollicitatievragen voor 2026

Technisch overzicht van Django 6.0: CompositePrimaryKey voor meervoudige sleutels, het native @task-framework voor achtergrondverwerking, template partials, CSP-middleware en veelgestelde Django-sollicitatievragen voor Python-ontwikkelaars.

Overzicht van nieuwe functies in Django 6.0 met samengestelde primaire sleutels en achtergrondtaken

Django 6.0, gepubliceerd in december 2025, levert een verzameling kernfunctionaliteiten waar de Django-gemeenschap jarenlang op heeft gewacht. Van samengestelde primaire sleutels en een ingebouwd takensysteem tot template partials en native Content Security Policy-ondersteuning: het framework vermindert de afhankelijkheid van externe pakketten en biedt ontwikkelaars een compactere, krachtigere toolbox voor het bouwen van productieapplicaties. Dit artikel behandelt elke belangrijke toevoeging met werkende codevoorbeelden en sluit af met veelgestelde sollicitatievragen die in 2026 relevant zijn voor Python-backendposities.

Django-versietijdlijn

Django 5.2 LTS verscheen in april 2025 en introduceerde samengestelde primaire sleutels als eerste stabiele implementatie. Django 6.0 volgde in december 2025 met achtergrondtaken, template partials en CSP-middleware. Django 6.1 bevindt zich momenteel in actieve ontwikkeling. Productieomgevingen die langdurige ondersteuning vereisen, kunnen terugvallen op Django 5.2 LTS.

Samengestelde primaire sleutels met CompositePrimaryKey

Gedurende het bestaan van Django was elk model gebonden aan een enkelvoudige kolomsleutel als primaire sleutel. Die architecturale beperking dwong ontwikkelaars tot het aanmaken van kunstmatige id-kolommen op tussentabellen, zelfs wanneer de combinatie van twee buitenlandse sleutels al volstond als unieke identificator. Django 5.2 doorbreekt die conventie met de klasse CompositePrimaryKey, waarmee meervoudige kolomsleutels rechtstreeks in de ORM gedefinieerd kunnen worden.

De voordelen zijn concreet: surrogaat-AutoField-kolommen op tussentabellen worden overbodig, de database handhaaft uniciteit op het niveau van de samengestelde sleutel, en de opslagruimte voor geindexeerde zoekbewerkingen daalt. Het onderstaande voorbeeld toont een voorraadmodel waarin de combinatie van product en magazijn de natuurlijke primaire sleutel vormt.

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)

Het Inventory-model genereert een PRIMARY KEY (product_id, warehouse_id)-constraint op databaseniveau. Er verschijnt geen extra id-kolom in de tabel. Het veld pk ontvangt de namen van de onderliggende databasekolommen -- niet de veldnamen van het Django-model zelf. Dit onderscheid is van belang bij velden waarvan de kolomnaam afwijkt van de modelveldnaam.

Bevragingen op samengestelde sleutels

In Python worden samengestelde primaire sleutels weergegeven als tuples. Filteren, ophalen en toewijzen verlopen via dezelfde tuple-interface, terwijl de vertrouwde ORM-syntax grotendeels ongewijzigd blijft.

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"

Bij het werken met samengestelde sleutels gelden drie beperkingen. Ten eerste kan een standaard ForeignKey niet verwijzen naar een model met een samengestelde primaire sleutel; hiervoor dient ForeignObject als alternatief. Ten tweede biedt de Django-beheersinterface geen ondersteuning voor modellen met samengestelde sleutels, waardoor CRUD-bewerkingen via de admin niet beschikbaar zijn. Ten derde vereist het omschakelen van een bestaande tabel naar samengestelde sleutels handmatige SQL, omdat het migratiesysteem deze transformatie niet automatisch kan uitvoeren.

Ingebouwd Background Tasks Framework in Django 6.0

Het uitvoeren van code buiten de verzoek-antwoordcyclus vereiste tot Django 6.0 het opzetten van Celery, Django-Q of een vergelijkbaar extern takensysteem. Django 6.0 bevat een native takensysteem dat de definitie en het in de wachtrij plaatsen van taken afhandelt zonder dat hiervoor extra infrastructuur vereist is tijdens de ontwikkelfase.

De @task-decorator markeert een functie als wachtrijbaar. Het aanroepen van .enqueue() op de gedecoreerde functie stuurt de taak naar een backend voor asynchrone uitvoering. Het ontwerp scheidt taakdefinitie van taakuitvoering: Django beheert de wachtrij, maar een afzonderlijk workerproces voert de taken daadwerkelijk uit.

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

Het dispatchen vanuit een view verloopt via de .enqueue()-methode. De argumenten worden geserialiseerd en doorgegeven aan de geconfigureerde backend. Het verzoek aan de gebruiker keert onmiddellijk terug, terwijl de taak op de achtergrond wordt verwerkt.

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"})

De TASKS-instelling in settings.py bepaalt welke backend wordt gebruikt. Django bevat twee ingebouwde backends die geschikt zijn voor ontwikkeling en testen. Productie-implementaties vereisen een backend die verbinding maakt met een berichtenmakelaar zoals Redis of RabbitMQ.

Achtergrondtaken versus Celery

Het ingebouwde takensysteem van Django dekt eenvoudige toepassingsgevallen: fire-and-forget-taken, het verzenden van e-mails en het genereren van rapporten. Voor geavanceerde mogelijkheden zoals taakkoppeling (chains, chords), periodieke planning via Celery Beat, snelheidsbeperking of resultaatbackends blijft Celery de gevestigde keuze. Het native systeem blinkt uit in eenvoud van configuratie en lagere operationele overhead.

Template Partials voor herbruikbare fragmenten

Django 6.0 introduceert de templatetags {% partialdef %} en {% partial %}, waarmee benoemde, herbruikbare fragmenten binnen een enkel templatebestand gedefinieerd kunnen worden. Dit vermindert de noodzaak voor afzonderlijke include-bestanden die verspreid raken over de templatemap.

Het meest voorkomende toepassingsgeval betreft situaties waarin meerdere visuele representaties van hetzelfde datamodel naast elkaar bestaan. Een product verschijnt als kaart in een catalogusoverzicht en als tabelrij in een voorraadbeheerscherm. Zonder template partials vereist elk van die weergaven een apart bestand. Met {% partialdef %} worden beide varianten logisch gegroepeerd.

html
<!-- templates/components/cards.html -->
{% partialdef product_card %}
<div class="card">
    <h3>{{ product.name }}</h3>
    <p class="price">{{ product.price|floatformat:2 }} EUR</p>
    <span class="stock {% if product.in_stock %}available{% else %}sold-out{% endif %}">
        {% if product.in_stock %}In Stock{% else %}Sold Out{% endif %}
    </span>
</div>
{% endpartialdef %}

{% partialdef product_row %}
<tr>
    <td>{{ product.name }}</td>
    <td>{{ product.price|floatformat:2 }} EUR</td>
    <td>{{ product.quantity }}</td>
</tr>
{% endpartialdef %}

De fragmentsyntaxis #naam in de {% include %}-tag maakt het mogelijk om precies het gewenste deel van een bestand te laden zonder het volledige template te verwerken.

html
<!-- templates/shop/catalog.html -->
{% extends "base.html" %}

{% block content %}
<div class="product-grid">
    {% for product in products %}
        {% include "components/cards.html#product_card" %}
    {% endfor %}
</div>
{% endblock %}

Dit patroon sluit naadloos aan bij HTMX-gebaseerde architecturen, waar de server specifieke pagina-onderdelen moet retourneren zonder de gehele pagina opnieuw te renderen. De verminderde bestandsproliferatie verbetert de navigeerbaarheid van de codebase, met name in grotere projecten waar de templatemap anders tientallen losse fragmentbestanden zou bevatten.

Klaar om je Django gesprekken te halen?

Oefen met onze interactieve simulatoren, flashcards en technische tests.

Native Content Security Policy Middleware

Django 6.0 voegt ingebouwde CSP-ondersteuning toe via ContentSecurityPolicyMiddleware. Voorheen was het externe pakket django-csp hiervoor noodzakelijk. Content Security Policy beschermt tegen cross-site scripting (XSS) en andere injectieaanvallen door te specificeren welke bronnen de browser mag laden en uitvoeren.

python
# settings.py
from django.utils.csp import CSP

MIDDLEWARE = [
    "django.middleware.security.SecurityMiddleware",
    "django.middleware.security.ContentSecurityPolicyMiddleware",
    # ... other middleware
]

SECURE_CSP = {
    "default-src": [CSP.SELF],
    "script-src": [CSP.SELF, CSP.NONCE],
    "style-src": [CSP.SELF, "https://fonts.googleapis.com"],
    "img-src": [CSP.SELF, "https:", "data:"],
    "font-src": [CSP.SELF, "https://fonts.gstatic.com"],
    "connect-src": [CSP.SELF],
}

# Report-only mode for testing (does not block, only reports violations)
SECURE_CSP_REPORT_ONLY = {
    "default-src": [CSP.SELF],
    "report-uri": ["/csp-report/"],
}

De constante CSP.NONCE genereert automatisch een unieke nonce per verzoek en injecteert deze in de scriptblokken van het template. Hierdoor kunnen legitieme inline scripts worden uitgevoerd, terwijl door aanvallers geinjecteerde scripts worden geblokkeerd. De report-only-modus via SECURE_CSP_REPORT_ONLY registreert schendingen zonder bronnen daadwerkelijk te blokkeren, wat nuttig is tijdens de uitrolfase om het beleid stapsgewijs af te stemmen op de applicatievereisten.

De CSP-middleware dient na SecurityMiddleware in de MIDDLEWARE-lijst te staan. Middleware die HTML wijzigt en na de CSP-middleware wordt geplaatst, zou inline scripts kunnen injecteren zonder geldig nonce-attribuut, waardoor het CSP-beleid die scripts blokkeert.

Overige belangrijke wijzigingen in Django 6.0

Naast de hierboven beschreven hoofdfuncties bevat Django 6.0 diverse verbeteringen die de dagelijkse ontwikkelpraktijk raken.

BigAutoField als standaard primaire sleutel. Nieuwe projecten maken voortaan gebruik van BigAutoField (64-bits) in plaats van AutoField (32-bits) voor automatisch gegenereerde primaire sleutels. De bovengrens van circa 2,1 miljard records per tabel wordt hiermee opgeheven. Bestaande projecten die DEFAULT_AUTO_FIELD niet expliciet hebben ingesteld, ontvangen een waarschuwing bij het uitvoeren van migraties.

Asynchrone paginering. De nieuwe klassen AsyncPaginator en AsyncPage brengen native asynchrone ondersteuning naar paginering. ASGI-gebaseerde views profiteren doordat de event loop niet wordt geblokkeerd tijdens het pagineren van queryresultaten, wat de doorvoer van applicaties op ASGI-servers aanzienlijk verbetert.

Automatische imports in de shell. Het commando manage.py shell importeert voortaan automatisch alle modellen en veelgebruikte Django-hulpmiddelen zoals django.db.models, django.utils.timezone en datetime. Het herhaaldelijk handmatig invoeren van importregels bij elke interactieve debugsessie behoort daarmee tot het verleden.

Gemoderniseerde e-mail-API. De e-mailklassen van Django maken nu gebruik van Python's email.message.EmailMessage in plaats van de verouderde MIME-klassen. Het samenstellen van complexe berichten met inline bijlagen, aangepaste headers en HTML-inhoud wordt hierdoor eenvoudiger en beter afgestemd op de standaardbibliotheek van Python.

Django-sollicitatievragen voor 2026

Technische sollicitatiegesprekken voor Python-backendposities behandelen in toenemende mate de nieuwere functionaliteiten van Django. De onderstaande vragen weerspiegelen de thema's die het vaakst terugkomen bij selectieprocedures in 2026.

Welk probleem lossen samengestelde primaire sleutels op en wat zijn de beperkingen?

Samengestelde primaire sleutels elimineren de noodzaak van een kunstmatige id-kolom wanneer de natuurlijke sleutel van een model uit meerdere kolommen bestaat. De database handhaaft de uniciteit op het niveau van de samengestelde sleutel, wat de data-integriteit versterkt en opslagruimte bespaart. De voornaamste beperkingen zijn het ontbreken van standaard ForeignKey-ondersteuning (hiervoor geldt ForeignObject), het niet beschikbaar zijn van de admin-interface voor deze modellen, en de noodzaak van handmatige SQL bij het omschakelen van bestaande tabellen. Daarnaast is het tuple-gebaseerde serialisatieformaat nog niet volledig compatibel met alle REST-framework-serializers.

Waarin verschilt het achtergrondtakensysteem van Django 6.0 van Celery?

Het native systeem is gericht op eenvoudige fire-and-forget-scenario's: e-mailbezorging, rapportgeneratie en externe API-aanroepen die de HTTP-cyclus niet mogen blokkeren. Het draait binnen het Django-proces en vereist geen externe berichtenmakelaar in de standaardconfiguratie. Celery biedt gedistribueerde verwerking over meerdere machines, geavanceerde wachtrijroutering, taakkoppeling, periodieke planning en monitoring. Voor applicaties met complexe orchestratiebehoefte of hoge doorvoervereisten blijft Celery het gevestigde instrument; het native systeem blinkt uit in configuratie-eenvoud.

Beschrijf de uitvoeringsvolgorde van Django-middleware en de positie van de CSP-middleware.

Django verwerkt middleware in de volgorde van de MIDDLEWARE-lijst. Binnenkomende verzoeken doorlopen de keten van boven naar beneden; uitgaande antwoorden van beneden naar boven. ContentSecurityPolicyMiddleware dient na SecurityMiddleware geplaatst te worden zodat beveiligingsheaders correct worden ingesteld. Een middleware die HTML aanpast en na de CSP-middleware staat, zou inline scripts kunnen injecteren zonder geldig nonce-attribuut, waardoor het CSP-beleid die scripts blokkeert. Het begrijpen van deze bidirectionele verwerkingsvolgorde is essentieel voor het diagnosticeren van problemen met beveiligingsheaders.

Wat zijn template partials en wanneer verdienen zij de voorkeur boven afzonderlijke include-bestanden?

Template partials stellen ontwikkelaars in staat meerdere benoemde fragmenten binnen een enkel templatebestand te definiƫren via {% partialdef naam %}. De {% include %}-tag laadt vervolgens een specifiek fragment met de syntaxis "bestand.html#naam". Dit vermindert bestandsproliferatie wanneer verwante variaties van een component logisch bij elkaar horen. Partials zijn bijzonder geschikt voor HTMX-integraties, waar de server gerichte fragmenten moet terugsturen, en voor projecten met uitgebreide templatemappen waar overzichtelijkheid een aandachtspunt vormt.

Migratie van Django 5.2 naar 6.0

Django 6.0 laat de ondersteuning voor Python 3.10 en 3.11 vallen. Het standaard DEFAULT_AUTO_FIELD wijzigt naar BigAutoField. De e-mailklassen maken nu gebruik van Python's moderne e-mail-API, wat code die afhankelijk is van verouderde MIME-interne structuren kan breken. Voer een volledige testsuite uit alvorens productieomgevingen bij te werken naar Django 6.0.

Conclusie

Django 6.0 versterkt het framework op meerdere fronten en vermindert de afhankelijkheid van externe pakketten voor veelvoorkomende toepassingsgevallen:

  • Samengestelde primaire sleutels (CompositePrimaryKey) maken surrogaatkolommen op tussentabellen overbodig en brengen de ORM in lijn met het standaard relationele databasemodel
  • Het ingebouwde @task- en .enqueue()-systeem verwerkt eenvoudige achtergrondtaken zonder de operationele overhead van Celery
  • Template partials ({% partialdef %}) groeperen verwante templatefragmenten in een enkel bestand en verminderen bestandsproliferatie in de templatemap
  • Native CSP-middleware (ContentSecurityPolicyMiddleware) vervangt het externe pakket django-csp met automatische nonce-generatie per verzoek
  • Django 6.0 hanteert BigAutoField als standaard, voegt asynchrone paginering toe, automatiseert shell-imports en adopteert Python's moderne e-mail-API
  • Sollicitatievoorbereiding dient de beperkingen van samengestelde sleutels, de afwegingen tussen het native takensysteem en Celery, en de verwerkingsvolgorde van middleware te omvatten

Begin met oefenen!

Test je kennis met onze gespreksimulatoren en technische tests.

Tags

#django
#python
#composite-primary-keys
#background-tasks
#django-6

Delen

Gerelateerde artikelen