# Django 6.0 ในปี 2026: Composite Primary Key, Background Task และคำถามสัมภาษณ์งาน > คู่มือฉบับสมบูรณ์เกี่ยวกับ Django 6.0 ครอบคลุม composite primary key, framework background task ในตัว, template partial, CSP middleware พร้อมตัวอย่างโค้ดจริงและการเตรียมตัวสัมภาษณ์ - Published: 2026-06-09 - Updated: 2026-06-09 - Author: SharpSkill - Tags: django, python, composite-primary-keys, background-tasks, interview - Reading time: 8 min --- Django 6.0 ซึ่งเปิดตัวในเดือนธันวาคม 2025 นำเสนอ framework background task ในตัว, template partial และการรองรับ Content Security Policy แบบ native มาสู่ web framework ของ Python ที่ได้รับความนิยมสูงสุด เมื่อรวมกับ composite primary key ที่เปิดตัวใน Django 5.2 ระบบนิเวศของ Django ในปี 2026 มอบชุดเครื่องมือที่ทรงพลังยิ่งขึ้นอย่างมากสำหรับการสร้างแอปพลิเคชัน production > **ไทม์ไลน์เวอร์ชัน Django ในปี 2026** > > Django 5.2 LTS (เมษายน 2025) เปิดตัว composite primary key Django 6.0 (ธันวาคม 2025) เพิ่ม background task, template partial และ CSP middleware Django 6.1 กำลังอยู่ระหว่างการพัฒนาพร้อม field fetch mode ## Composite Primary Key ด้วย CompositePrimaryKey ตลอด 18 ปีที่ผ่านมา Django บังคับให้ทุก model ใช้ primary key แบบคอลัมน์เดียว Django 5.2 ได้เปลี่ยนแปลงสิ่งนี้ด้วย class [`CompositePrimaryKey`](https://docs.djangoproject.com/en/6.0/topics/composite-primary-key/) ซึ่งทำให้สามารถใช้ primary key แบบหลายคอลัมน์ได้โดยตรงใน ORM Composite primary key ช่วยขจัดความจำเป็นในการใช้คอลัมน์ surrogate `AutoField` บน junction table และ model ใดก็ตามที่ natural key ครอบคลุมหลายคอลัมน์ ฐานข้อมูลบังคับใช้ความเป็นเอกลักษณ์ในระดับ primary key ลดค่าใช้จ่ายในการจัดเก็บและปรับปรุงประสิทธิภาพการ query บน 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` ด้านบนสร้าง constraint `PRIMARY KEY (product_id, warehouse_id)` ในระดับฐานข้อมูล ไม่มีคอลัมน์ `id` เพิ่มเติมถูกสร้างขึ้น ### การ Query Composite Key Composite primary key ถูกแสดงเป็น tuple ใน Python การ filter, fetch และ assign ทำงานผ่าน tuple interface นี้ ```python # views.py from .models import Inventory, Product, Warehouse # สร้าง record 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 ) # เข้าถึง composite pk ในรูปแบบ tuple print(item.pk) # (1, "WH-A") # Filter ด้วย composite pk result = Inventory.objects.filter(pk=(1, "WH-A")).first() # กำหนด composite pk โดยตรง new_item = Inventory(pk=(2, "WH-B")) print(new_item.product_id) # 2 print(new_item.warehouse_id) # "WH-B" ``` ข้อจำกัดสามประการที่ควรทราบในปัจจุบัน: `ForeignKey` ไม่สามารถอ้างอิงไปยัง model ที่มี composite primary key ได้ (ให้ใช้ `ForeignObject` แทน), Django admin ยังไม่รองรับ model composite key และการย้ายจาก single key ไปเป็น composite key หลังจากสร้างตารางแล้วต้องใช้ SQL แบบ manual ## Background Task ในตัวของ Django 6.0 ก่อน Django 6.0 การรันโค้ดนอกวงจร request-response จำเป็นต้องใช้ [Celery](https://docs.celeryq.dev/en/stable/), Django-Q หรือ task queue ของบุคคลที่สามที่คล้ายกัน Django 6.0 มาพร้อมกับ [framework task](https://docs.djangoproject.com/en/6.0/topics/tasks/) แบบ native ที่จัดการทั้งการกำหนดและ enqueue task ได้ในตัว Decorator `@task` ทำเครื่องหมายฟังก์ชันใดก็ได้ว่าสามารถ enqueue ได้ การเรียก `.enqueue()` บนฟังก์ชันที่ถูก decorate จะส่งไปยัง backend เพื่อประมวลผลแบบ asynchronous Framework นี้แยกการกำหนด task ออกจากการประมวลผล task: Django จัดการคิว แต่ worker process แยกต่างหากจัดการการรัน 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 การสร้าง user ... # Enqueue task สำหรับประมวลผลเบื้องหลัง 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"}) ``` การตั้งค่า `TASKS` ใน `settings.py` กำหนดค่า backend Django มี backend ในตัวสองตัวสำหรับ development และ testing การ deploy ใน production ต้องใช้ backend จากบุคคลที่สามหรือ implementation แบบกำหนดเองที่เชื่อมต่อกับ message broker > **Background task เทียบกับ Celery** > > Framework task ในตัวของ Django ครอบคลุมกรณีการใช้งานแบบง่าย: fire-and-forget task, การส่งอีเมล, การสร้างรายงาน สำหรับฟีเจอร์ขั้นสูงเช่น task chaining, การตั้งเวลาแบบ periodic, rate limiting หรือ result backend นั้น [Celery](/blog/django/django-celery-async-tasks-interview-2026) ยังคงเป็นตัวเลือกมาตรฐาน ## Template Partial สำหรับ Fragment ที่นำกลับมาใช้ซ้ำได้ Django 6.0 เปิดตัว template tag `{% partialdef %}` และ `{% partial %}` ซึ่งช่วยให้สามารถกำหนด fragment ของ template ที่มีชื่อและนำกลับมาใช้ซ้ำได้ภายในไฟล์เดียว ลดความจำเป็นในการสร้างไฟล์ include ขนาดเล็กที่กระจัดกระจายอยู่ในไดเรกทอรี template Partial ถูกกำหนดครั้งเดียวด้วย `{% partialdef %}` และ render ได้ทุกที่ใน template เดียวกัน (หรือจาก template อื่น) ด้วย `{% partial %}` นอกจากนี้ partial ยังรับ syntax มาตรฐาน `template_name#partial_name` กับ `{% include %}` ได้อีกด้วย ```html {% partialdef product_card %}

{{ product.name }}

{{ product.price|floatformat:2 }} EUR

{% if product.in_stock %}In Stock{% else %}Sold Out{% endif %}
{% endpartialdef %} {% partialdef product_row %} {{ product.name }} {{ product.price|floatformat:2 }} EUR {{ product.quantity }} {% endpartialdef %} ``` ```html {% extends "base.html" %} {% block content %}
{% for product in products %} {% include "components/cards.html#product_card" %} {% endfor %}
{% endblock %} ``` วิธีนี้เก็บ markup ที่เกี่ยวข้องไว้ด้วยกัน แทนที่จะสร้าง `_product_card.html` และ `_product_row.html` เป็นไฟล์แยก partial ทั้งสองจะอยู่ในไฟล์ component `cards.html` ไฟล์เดียว ## CSP Middleware แบบ Native Django 6.0 เพิ่ม[การรองรับ CSP ในตัว](https://docs.djangoproject.com/en/6.0/ref/middleware/#content-security-policy-middleware) ผ่าน `ContentSecurityPolicyMiddleware` ก่อนหน้านี้จำเป็นต้องใช้ package บุคคลที่สาม `django-csp` CSP header แจ้งเบราว์เซอร์ว่าแหล่งที่มาของเนื้อหาใด (script, style, รูปภาพ, font) ที่ได้รับอนุญาตให้โหลดบนหน้าเว็บ ซึ่งช่วยลดความเสี่ยงจากการโจมตี cross-site scripting (XSS) และ data injection ```python # settings.py from django.utils.csp import CSP MIDDLEWARE = [ "django.middleware.security.SecurityMiddleware", "django.middleware.security.ContentSecurityPolicyMiddleware", # ... 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 สำหรับ testing (ไม่บล็อก เพียงรายงานการละเมิด) SECURE_CSP_REPORT_ONLY = { "default-src": [CSP.SELF], "report-uri": ["/csp-report/"], } ``` ค่าคงที่ `CSP.NONCE` ทำงานร่วมกับ context processor `csp()` เพื่อแทรก nonce ต่อ request ลงใน template script inline ที่ถูกแท็กด้วย nonce นี้จะผ่านการตรวจสอบ CSP ส่วน script อื่นทั้งหมดจะถูกบล็อก ## การเปลี่ยนแปลงสำคัญอื่นๆ ใน Django 6.0 นอกเหนือจากฟีเจอร์หลัก Django 6.0 ยังรวมการเปลี่ยนแปลงหลายอย่างที่ส่งผลต่อการพัฒนาในชีวิตประจำวัน **BigAutoField เป็น primary key เริ่มต้น** โปรเจกต์ใหม่จะใช้ `BigAutoField` (64-bit) แทน `AutoField` (32-bit) สำหรับ primary key ที่สร้างอัตโนมัติ โปรเจกต์ที่มีอยู่จะไม่ได้รับผลกระทบเว้นแต่ `DEFAULT_AUTO_FIELD` จะถูกเปลี่ยนอย่างชัดเจน ซึ่งป้องกันปัญหา integer overflow ที่แอปพลิเคชันที่มี traffic สูงจะพบเจอในที่สุดเมื่อใช้ key 32-bit **Pagination แบบ async** Class `AsyncPaginator` และ `AsyncPage` ใหม่นำการรองรับ async แบบ native มาสู่การแบ่งหน้า ซึ่งมีประโยชน์ใน async view ที่ query ฐานข้อมูลผ่าน async ORM interface ของ Django **Auto-import ใน shell** คำสั่ง `manage.py shell` จะ import model ทั้งหมดและ utility ของ Django ที่ใช้บ่อยโดยอัตโนมัติ ไม่ต้องพิมพ์ `from myapp.models import *` ทุกครั้งที่เริ่ม session shell **API อีเมลสมัยใหม่** class อีเมลของ Django ใช้ `email.message.EmailMessage` ของ Python แทน class MIME แบบเก่า ปรับปรุงการจัดการ Unicode และทำให้การจัดการไฟล์แนบง่ายขึ้น ## คำถามสัมภาษณ์ Django สำหรับปี 2026 การสัมภาษณ์ด้านเทคนิคในปี 2026 ครอบคลุมฟีเจอร์ใหม่ของ Django มากขึ้นควบคู่กับพื้นฐานด้าน ORM, middleware และ REST framework ด้านล่างนี้คือคำถามที่สะท้อนสถานะปัจจุบันของ framework **Composite primary key แก้ปัญหาอะไร และมีข้อจำกัดอะไรบ้าง?** Composite primary key ขจัดคอลัมน์ surrogate key บน model ที่ natural key ครอบคลุมหลาย field (junction table, audit log, versioned record) ฐานข้อมูลบังคับใช้ความเป็นเอกลักษณ์และการทำ index ในระดับ primary key ข้อจำกัดปัจจุบันรวมถึงไม่รองรับ `ForeignKey` ไปยัง model composite key, ไม่มีการรวมเข้ากับ Django admin และไม่มีเส้นทาง migration จาก single key ไปเป็น composite key หลังจากสร้างตารางแล้ว **Framework background task ของ Django 6.0 แตกต่างจาก Celery อย่างไร?** Decorator `@task` ในตัวของ Django และ method `.enqueue()` มอบ task queue ที่เบาสำหรับการทำงาน async แบบง่าย ไม่รวมการตั้งเวลา task แบบ periodic, task chaining, rate limiting หรือการจัดเก็บผลลัพธ์ Celery ยังคงจำเป็นสำหรับการจัดการ workflow ที่ซับซ้อน framework ในตัวเหมาะสำหรับ fire-and-forget task เช่น การส่งอีเมลหรือการ trigger webhook **อธิบายลำดับการทำงานของ middleware ใน Django และ CSP middleware มีบทบาทอย่างไร** Django ประมวลผล middleware ตามลำดับในช่วง request phase (บนลงล่างใน `MIDDLEWARE`) และในลำดับย้อนกลับในช่วง response phase `ContentSecurityPolicyMiddleware` ทำงานในช่วง response phase เพิ่ม CSP header ก่อนที่ response จะถึง client การวางไว้หลัง `SecurityMiddleware` ทำให้มั่นใจว่า HTTPS redirect เกิดขึ้นก่อนที่ CSP header จะถูกนำไปใช้ สำหรับข้อมูลเพิ่มเติมเกี่ยวกับหัวข้อนี้ ดูที่ [คำถามสัมภาษณ์ Django middleware](/technologies/django/interview-questions/django-middleware) **Template partial คืออะไร และเมื่อไหร่ควรใช้แทน `{% include %}`?** Template partial (`{% partialdef %}` / `{% partial %}`) กำหนด fragment ที่มีชื่อภายในไฟล์ template เดียว ช่วยลดการกระจัดกระจายของไฟล์เมื่อเทียบกับไฟล์ include แยก partial เหมาะอย่างยิ่งสำหรับ component ขนาดเล็กที่เกี่ยวข้องกันอย่างใกล้ชิด (รูปแบบ card ที่แตกต่าง, รูปแบบแถวตาราง) ที่อยู่ใน template logic เดียวกัน สำหรับ component ขนาดใหญ่ที่เป็นอิสระซึ่งใช้ในหน้าที่ไม่เกี่ยวข้องกัน ไฟล์ template แยกกับ `{% include %}` ยังคงชัดเจนกว่า > **การย้ายจาก Django 5.2 ไปยัง 6.0** > > Django 6.0 ยุติการรองรับ Python 3.10 และ 3.11 ค่าเริ่มต้น `DEFAULT_AUTO_FIELD` เปลี่ยนเป็น `BigAutoField` class อีเมลใช้ API อีเมลสมัยใหม่ของ Python ซึ่งอาจทำให้โค้ดที่พึ่งพา internal MIME แบบเก่าเกิดปัญหาได้ ควรทดสอบอย่างละเอียดก่อนอัปเกรดแอปพลิเคชัน production ## สรุป - Composite primary key (`CompositePrimaryKey`) ขจัดคอลัมน์ surrogate บน junction table — กำหนดแอตทริบิวต์ `pk` เป็น tuple ของชื่อ field และ query ด้วย tuple - Framework `@task` / `.enqueue()` ในตัวจัดการ background work แบบง่ายโดยไม่ต้องใช้ Celery แม้ว่า Celery ยังคงจำเป็นสำหรับการตั้งเวลาและ chaining - Template partial (`{% partialdef %}` / `{% partial %}`) จัดกลุ่ม fragment ของ template ที่เกี่ยวข้องไว้ในไฟล์เดียว เข้าถึงผ่าน syntax `template_name#partial_name` - CSP middleware แบบ native (`ContentSecurityPolicyMiddleware`) ทดแทน `django-csp` สำหรับกรณีการใช้งานส่วนใหญ่ กำหนดค่าผ่าน `SECURE_CSP` ใน settings - Django 6.0 ใช้ `BigAutoField` เป็นค่าเริ่มต้น เพิ่ม pagination แบบ async, auto-import ใน shell และนำ API อีเมลสมัยใหม่ของ Python มาใช้ - การเตรียมตัวสัมภาษณ์ควรครอบคลุมข้อจำกัดของ composite key, การเปรียบเทียบ framework task กับ Celery และลำดับการทำงานของ middleware พร้อม layer CSP ใหม่ --- Source: SharpSkill (https://sharpskill.dev), tech interview preparation for your real stack. HTML version of this page: https://sharpskill.dev/th/blog/django/django-6-composite-primary-keys-background-tasks-2026