Django 6.0 năm 2026: Composite Primary Key, Background Task và Câu hỏi phỏng vấn

Hướng dẫn toàn diện về Django 6.0 bao gồm composite primary key, framework background task tích hợp, template partial, CSP middleware cùng ví dụ code thực tế và chuẩn bị phỏng vấn.

Hướng dẫn Django 6.0 composite primary key và background task

Django 6.0, phát hành vào tháng 12 năm 2025, mang đến framework background task tích hợp, template partial và hỗ trợ Content Security Policy native cho framework web Python phổ biến nhất. Kết hợp với composite primary key được giới thiệu trong Django 5.2, hệ sinh thái Django năm 2026 cung cấp bộ công cụ mạnh mẽ hơn đáng kể để xây dựng ứng dụng production.

Dòng thời gian phiên bản Django năm 2026

Django 5.2 LTS (tháng 4/2025) giới thiệu composite primary key. Django 6.0 (tháng 12/2025) bổ sung background task, template partial và CSP middleware. Django 6.1 hiện đang được phát triển với field fetch mode.

Composite Primary Key với CompositePrimaryKey

Trong suốt 18 năm, Django buộc mọi model phải sử dụng primary key đơn cột. Django 5.2 đã thay đổi điều đó với class CompositePrimaryKey, cho phép primary key đa cột trực tiếp trong ORM.

Composite primary key loại bỏ nhu cầu sử dụng cột surrogate AutoField trên các bảng junction và bất kỳ model nào có natural key trải rộng nhiều cột. Cơ sở dữ liệu thực thi tính duy nhất ở cấp primary key, giảm chi phí lưu trữ và cải thiện hiệu năng truy vấn trên các indexed lookup.

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)

Model Inventory ở trên tạo constraint PRIMARY KEY (product_id, warehouse_id) ở cấp cơ sở dữ liệu. Không có cột id bổ sung nào được tạo ra.

Truy vấn Composite Key

Composite primary key được biểu diễn dưới dạng tuple trong Python. Việc filter, fetch và gán đều hoạt động thông qua giao diện tuple này.

python
# views.py
from .models import Inventory, Product, Warehouse

# Tạo bản ghi
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
)

# Truy cập composite pk dưới dạng tuple
print(item.pk)  # (1, "WH-A")

# Filter theo composite pk
result = Inventory.objects.filter(pk=(1, "WH-A")).first()

# Gán composite pk trực tiếp
new_item = Inventory(pk=(2, "WH-B"))
print(new_item.product_id)  # 2
print(new_item.warehouse_id)  # "WH-B"

Ba hạn chế cần lưu ý hiện tại: ForeignKey không thể tham chiếu đến model có composite primary key (sử dụng ForeignObject thay thế), Django admin chưa hỗ trợ model composite key, và việc chuyển đổi giữa single và composite key sau khi tạo bảng đòi hỏi SQL thủ công.

Background Task tích hợp trong Django 6.0

Trước Django 6.0, việc chạy code bên ngoài vòng request-response đòi hỏi Celery, Django-Q hoặc các task queue bên thứ ba tương tự. Django 6.0 cung cấp một framework task native xử lý việc định nghĩa và enqueue task ngay trong framework.

Decorator @task đánh dấu bất kỳ hàm nào là có thể enqueue. Việc gọi .enqueue() trên hàm đã được decorate sẽ gửi nó đến backend để thực thi bất đồng bộ. Framework tách biệt việc định nghĩa task khỏi việc thực thi task: Django xử lý hàng đợi, nhưng một tiến trình worker riêng biệt xử lý việc chạy task.

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
python
# views.py
from .tasks import send_welcome_email, generate_report

def register_user(request):
    # ... logic tạo user ...
    # Enqueue task để thực thi nền
    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"})

Cài đặt TASKS trong settings.py cấu hình backend. Django cung cấp hai backend tích hợp cho development và testing. Triển khai production đòi hỏi backend bên thứ ba hoặc triển khai tùy chỉnh kết nối đến message broker.

Background task vs Celery

Framework task tích hợp của Django phù hợp cho các trường hợp sử dụng đơn giản: fire-and-forget task, gửi email, tạo báo cáo. Đối với các tính năng nâng cao như task chaining, lập lịch định kỳ, rate limiting hoặc result backend, Celery vẫn là lựa chọn tiêu chuẩn.

Template Partial cho các Fragment tái sử dụng

Django 6.0 giới thiệu các tag template {% partialdef %}{% partial %}. Chúng cho phép định nghĩa các fragment template có tên, có thể tái sử dụng trong một file duy nhất, giảm nhu cầu tạo nhiều file include nhỏ rải rác khắp thư mục template.

Partial được định nghĩa một lần với {% partialdef %} và render ở bất kỳ đâu trong cùng template (hoặc từ template khác) với {% partial %}. Partial cũng chấp nhận cú pháp tiêu chuẩn template_name#partial_name với {% include %}.

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 %}
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 %}

Cách tiếp cận này giữ các markup liên quan ở cùng nhau. Thay vì tạo _product_card.html_product_row.html dưới dạng file riêng biệt, cả hai partial đều nằm trong một file component cards.html duy nhất.

Sẵn sàng chinh phục phỏng vấn Django?

Luyện tập với mô phỏng tương tác, flashcards và bài kiểm tra kỹ thuật.

CSP Middleware tích hợp

Django 6.0 bổ sung hỗ trợ CSP tích hợp thông qua ContentSecurityPolicyMiddleware. Trước đây, điều này đòi hỏi package bên thứ ba django-csp.

Header CSP thông báo cho trình duyệt biết nguồn nội dung nào (script, style, hình ảnh, font) được phép tải trên trang. Điều này giảm thiểu các cuộc tấn công cross-site scripting (XSS) và data injection.

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

MIDDLEWARE = [
    "django.middleware.security.SecurityMiddleware",
    "django.middleware.security.ContentSecurityPolicyMiddleware",
    # ... middleware khác
]

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],
}

# Chế độ report-only để testing (không chặn, chỉ báo cáo vi phạm)
SECURE_CSP_REPORT_ONLY = {
    "default-src": [CSP.SELF],
    "report-uri": ["/csp-report/"],
}

Hằng số CSP.NONCE hoạt động với context processor csp() để chèn nonce theo từng request vào template. Các script inline được gắn nonce này sẽ vượt qua kiểm tra CSP; tất cả các script khác bị chặn.

Các thay đổi đáng chú ý khác trong Django 6.0

Ngoài các tính năng chính, Django 6.0 bao gồm một số thay đổi ảnh hưởng đến công việc phát triển hàng ngày.

BigAutoField làm primary key mặc định. Các dự án mới giờ sử dụng BigAutoField (64-bit) thay vì AutoField (32-bit) cho primary key tự động sinh. Các dự án hiện có không bị ảnh hưởng trừ khi DEFAULT_AUTO_FIELD được thay đổi rõ ràng. Điều này ngăn chặn vấn đề integer overflow mà các ứng dụng có lưu lượng truy cập cao cuối cùng sẽ gặp phải với key 32-bit.

Phân trang async. Các class AsyncPaginatorAsyncPage mới mang đến hỗ trợ async native cho phân trang, hữu ích trong các view async truy vấn cơ sở dữ liệu qua giao diện ORM async của Django.

Auto-import trong shell. Lệnh manage.py shell giờ tự động import tất cả model và các tiện ích Django phổ biến. Không cần phải gõ from myapp.models import * mỗi khi bắt đầu phiên shell.

API email hiện đại. Các class email của Django giờ sử dụng email.message.EmailMessage của Python thay vì các class MIME legacy, cải thiện xử lý Unicode và đơn giản hóa quản lý tệp đính kèm.

Câu hỏi phỏng vấn Django năm 2026

Các cuộc phỏng vấn kỹ thuật năm 2026 ngày càng đề cập nhiều đến các tính năng mới của Django cùng với các kiến thức cơ bản về ORM, middleware và REST framework. Dưới đây là những câu hỏi phản ánh trạng thái hiện tại của framework.

Composite primary key giải quyết vấn đề gì và có những hạn chế nào?

Composite primary key loại bỏ các cột surrogate key trên các model có natural key trải rộng nhiều field (bảng junction, audit log, bản ghi có version). Cơ sở dữ liệu thực thi tính duy nhất và lập index ở cấp primary key. Các hạn chế hiện tại bao gồm không hỗ trợ ForeignKey đến model composite key, không tích hợp Django admin, và không có đường dẫn migration từ single sang composite key sau khi tạo bảng.

Framework background task của Django 6.0 khác gì so với Celery?

Decorator @task tích hợp của Django và method .enqueue() cung cấp task queue nhẹ cho các thao tác async đơn giản. Framework không bao gồm lập lịch task định kỳ, task chaining, rate limiting hoặc lưu trữ kết quả. Celery vẫn cần thiết cho việc điều phối workflow phức tạp. Framework tích hợp phù hợp cho fire-and-forget task như gửi email hoặc kích hoạt webhook.

Giải thích thứ tự thực thi middleware của Django và CSP middleware đóng vai trò như thế nào.

Django xử lý middleware theo thứ tự trong giai đoạn request (từ trên xuống dưới trong MIDDLEWARE) và theo thứ tự ngược lại trong giai đoạn response. ContentSecurityPolicyMiddleware chạy trong giai đoạn response, thêm header CSP trước khi response đến client. Đặt nó sau SecurityMiddleware đảm bảo redirect HTTPS xảy ra trước khi header CSP được áp dụng. Để tìm hiểu thêm về chủ đề này, tham khảo câu hỏi phỏng vấn Django middleware.

Template partial là gì và khi nào nên thay thế {% include %}?

Template partial ({% partialdef %} / {% partial %}) định nghĩa các fragment có tên trong một file template duy nhất. Chúng giảm sự phân tán file so với các file include riêng biệt. Partial lý tưởng cho các component nhỏ, liên quan chặt chẽ (các biến thể card, định dạng hàng bảng) thuộc cùng một template logic. Đối với các component lớn, độc lập được sử dụng trên các trang không liên quan, file template riêng biệt với {% include %} vẫn rõ ràng hơn.

Migration từ Django 5.2 lên 6.0

Django 6.0 ngừng hỗ trợ Python 3.10 và 3.11. Giá trị mặc định DEFAULT_AUTO_FIELD thay đổi thành BigAutoField. Các class email giờ sử dụng API email hiện đại của Python, có thể gây lỗi cho code phụ thuộc vào internal MIME legacy. Cần kiểm tra kỹ lưỡng trước khi nâng cấp ứng dụng production.

Kết luận

  • Composite primary key (CompositePrimaryKey) loại bỏ cột surrogate trên bảng junction — định nghĩa thuộc tính pk dưới dạng tuple tên field và truy vấn bằng tuple
  • Framework @task / .enqueue() tích hợp xử lý background work đơn giản mà không cần Celery, dù Celery vẫn cần thiết cho lập lịch và chaining
  • Template partial ({% partialdef %} / {% partial %}) nhóm các fragment template liên quan trong một file, truy cập qua cú pháp template_name#partial_name
  • CSP middleware tích hợp (ContentSecurityPolicyMiddleware) thay thế django-csp cho hầu hết các trường hợp sử dụng, được cấu hình qua SECURE_CSP trong settings
  • Django 6.0 mặc định dùng BigAutoField, bổ sung phân trang async, auto-import trong shell và áp dụng API email hiện đại của Python
  • Chuẩn bị phỏng vấn nên bao gồm hạn chế của composite key, so sánh framework task vs Celery, và thứ tự thực thi middleware với layer CSP mới

Bắt đầu luyện tập!

Kiểm tra kiến thức với mô phỏng phỏng vấn và bài kiểm tra kỹ thuật.

Thẻ

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

Chia sẻ

Bài viết liên quan