Django 5.2 Custom Middleware และ Signal Handling: คู่มือเตรียมสัมภาษณ์เชิงเทคนิค
คู่มือเชิงลึก Django 5.2 custom middleware และ signal handling สำหรับการสัมภาษณ์เชิงเทคนิค ครอบคลุม request pipeline, async middleware, post_save, pre_save, custom signals และแนวทางปฏิบัติที่ดีสำหรับ production

Custom middleware และ signal handling ใน Django 5.2 เป็นสองหัวข้อพื้นฐานที่ปรากฏในการสัมภาษณ์เชิงเทคนิคของ Django แทบทุกครั้ง การทำความเข้าใจว่า request ไหลผ่าน middleware stack อย่างไร และ signal ช่วยแยกส่วน logic ของแอปพลิเคชันอย่างไร คือสิ่งที่แยกผู้สมัครที่ท่องจำเอกสารออกจากผู้สมัครที่สร้างแอปพลิเคชัน Django ระดับ production ได้จริง ทั้ง middleware และ signal เป็นกลไกที่ทำงานอยู่เบื้องหลังของ Django application ทุกตัว แต่การเข้าใจรายละเอียดปลีกย่อยในเชิงสถาปัตยกรรมจะช่วยให้สามารถตอบคำถามสัมภาษณ์ได้อย่างมั่นใจ ไม่ว่าจะเป็นคำถามเกี่ยวกับลำดับการทำงานของ middleware, ความแตกต่างระหว่าง pre_save กับ post_save หรือการออกแบบ custom signal สำหรับ domain events
Django middleware ประมวลผล request จากบนลงล่างตามลำดับใน MIDDLEWARE list และประมวลผล response จากล่างขึ้นบน ส่วน signal ทำงานตามรูปแบบ publish-subscribe โดย sender กระจายเหตุการณ์ออกไป และ receiver ตอบสนองโดยไม่ต้องมีการเชื่อมต่อโดยตรง แนวคิดทั้งสองนี้มักปรากฏในรอบสัมภาษณ์ระดับ senior เนื่องจากเป็นการทดสอบความเข้าใจเชิงสถาปัตยกรรม ไม่ใช่แค่ความรู้ด้าน syntax เท่านั้น
กลไกการทำงานของ Django Middleware
Middleware pipeline อยู่ระหว่าง web server กับ Django views โดยแต่ละ middleware component จะห่อหุ้ม component ถัดไป สร้างโครงสร้างแบบหัวหอม (onion-like structure) ที่ request ต้องผ่านเข้าไปทีละชั้น เมื่อ request เข้ามา Django จะเรียกแต่ละ middleware ตามลำดับที่กำหนดไว้ใน settings.MIDDLEWARE จากบนลงล่าง หลังจาก view ประมวลผลเสร็จและคืนค่า response กลับมา middleware stack เดิมจะประมวลผล response ในลำดับย้อนกลับจากล่างขึ้นบน
Django 5.2 ใช้รูปแบบ middleware สมัยใหม่ที่เริ่มนำมาใช้ตั้งแต่ Django 1.10 โดยแต่ละ middleware เป็น callable ที่รับ get_response ระหว่างการ initialize และประมวลผล request/response cycle ใน method __call__ โครงสร้างพื้นฐานมีดังนี้
# middleware.py - Basic middleware structure
class SimpleMiddleware:
def __init__(self, get_response):
self.get_response = get_response
# One-time configuration happens here at server start
def __call__(self, request):
# Code executed BEFORE the view (and later middleware)
response = self.get_response(request)
# Code executed AFTER the view (on the way back)
return responseMethod __init__ ทำงานเพียงครั้งเดียวเมื่อเซิร์ฟเวอร์เริ่มทำงาน จึงเป็นจุดที่เหมาะสำหรับการตั้งค่าที่ใช้ทรัพยากรสูง เช่น การโหลด configuration จากไฟล์ การสร้าง database connection pool หรือการ compile regular expression patterns ที่ใช้ซ้ำในทุก request ส่วน method __call__ จะถูกเรียกทุกครั้งที่มี request เข้ามา โดยโค้ดที่อยู่ก่อน self.get_response(request) จะทำงานในขาเข้า (request phase) และโค้ดที่อยู่หลังจะทำงานในขากลับ (response phase) จุดนี้เป็นแนวคิดสำคัญที่ผู้สัมภาษณ์มักถามเพื่อทดสอบความเข้าใจในลำดับการทำงานของ middleware
การสร้าง Request Logging Middleware
Request logging middleware เป็นตัวอย่างเชิงปฏิบัติที่แสดงให้เห็นวงจรชีวิตทั้งหมดของ middleware ได้อย่างชัดเจน การ implement นี้จะบันทึกข้อมูลเวลาที่ใช้ในการประมวลผล, request metadata รวมถึง HTTP method, path, IP address และ status code ของ response ทุกรายการลงใน structured log ซึ่งเป็นตัวอย่างที่ผู้สัมภาษณ์มักต้องการเห็นเพื่อประเมินความเข้าใจในระดับ production
# apps/core/middleware.py
import logging
import time
logger = logging.getLogger('django.request')
class RequestLoggingMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
start_time = time.monotonic()
# Attach metadata before view processing
request.start_time = start_time
response = self.get_response(request)
duration = time.monotonic() - start_time
logger.info(
'method=%s path=%s status=%d duration=%.3fs ip=%s',
request.method,
request.get_full_path(),
response.status_code,
duration,
request.META.get('REMOTE_ADDR'),
)
return response
def process_exception(self, request, exception):
# Called only when the view raises an exception
duration = time.monotonic() - getattr(request, 'start_time', 0)
logger.error(
'method=%s path=%s exception=%s duration=%.3fs',
request.method,
request.get_full_path(),
str(exception),
duration,
)
return None # Let Django's default exception handling continueการใช้ time.monotonic() แทน time.time() เป็นสิ่งที่ควรสังเกต เนื่องจาก monotonic clock ไม่ได้รับผลกระทบจากการปรับเวลาระบบ (system clock adjustment) ทำให้การวัดระยะเวลาแม่นยำกว่า นอกจากนี้ การแนบ start_time ไว้กับ request object ทำให้สามารถเข้าถึงค่านี้ได้ทั้งใน __call__ และ process_exception โดยไม่ต้องใช้ตัวแปร global
Hook process_exception เป็น method พิเศษของ middleware ที่ Django จะเรียกเฉพาะเมื่อ view เกิด exception ที่ไม่ได้จัดการ การ return None จะปล่อยให้ exception ไหลต่อไปยัง exception handler ตัวมาตรฐานของ Django ในขณะที่การ return HttpResponse จะตัดวงจร exception handling ทันที สิ่งนี้เป็นคำถามสัมภาษณ์ที่พบบ่อย เพราะเป็นการทดสอบว่าผู้สมัครเข้าใจ exception propagation ใน middleware stack หรือไม่
ลำดับของ Middleware: ทำไมจึงสำคัญ
ลำดับของ middleware ใน settings.py ส่งผลโดยตรงต่อพฤติกรรมของแอปพลิเคชัน การจัดลำดับผิดอาจทำให้เกิดปัญหาด้านความปลอดภัย หรือทำให้ middleware ไม่ทำงานตามที่คาดหวัง
# settings.py - Middleware ordering matters
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
# Custom middleware placed after Django's core stack
'apps.core.middleware.RequestLoggingMiddleware',
]SecurityMiddleware ควรอยู่ลำดับแรกเสมอ เนื่องจากมีหน้าที่ตั้งค่า security headers สำหรับทุก response รวมถึง HTTPS redirect SessionMiddleware ต้องอยู่ก่อน AuthenticationMiddleware เนื่องจากการยืนยันตัวตนต้องพึ่งพาข้อมูล session ที่โหลดมาจาก cookie แล้ว
คำถามสัมภาษณ์ที่พบบ่อยคือ ทำไม CsrfViewMiddleware ต้องอยู่หลัง SessionMiddleware คำตอบคือ การป้องกัน CSRF ใน Django สามารถใช้ session-based tokens ได้ ดังนั้น session จึงต้องถูกโหลดก่อน หากสลับลำดับ CSRF protection อาจทำงานไม่ถูกต้อง สำหรับ custom middleware ที่ไม่มีข้อกำหนดพิเศษด้านลำดับ แนะนำให้วางไว้ท้ายรายการ หลังจาก middleware หลักของ Django ทั้งหมด
Async Middleware ใน Django 5.2
Django 5.2 รองรับ asynchronous middleware อย่างเต็มรูปแบบ ซึ่งเป็นหัวข้อที่ผู้สัมภาษณ์ให้ความสนใจมากขึ้นเรื่อย เนื่องจาก async views และ ASGI deployment กำลังเป็นที่นิยม Async middleware มีความสำคัญอย่างยิ่งสำหรับ I/O-bound operations เช่น การเรียก external API, cache lookups หรือการตรวจสอบ rate limiting จาก Redis
# apps/core/middleware.py
import asyncio
import time
class AsyncTimingMiddleware:
# Mark this middleware as async-capable
async_capable = True
sync_capable = False
def __init__(self, get_response):
self.get_response = get_response
async def __call__(self, request):
start = time.monotonic()
# get_response is awaitable in async context
response = await self.get_response(request)
duration = time.monotonic() - start
response['X-Request-Duration'] = f'{duration:.4f}s'
return responseการตั้งค่า async_capable = True และ sync_capable = False จะบอก Django ว่า middleware นี้ทำงานได้เฉพาะในโหมด async เท่านั้น หากแอปพลิเคชันมีทั้ง sync views และ async views ให้ตั้งค่าทั้งสอง flag เป็น True แล้ว Django จะเลือกเรียก method ที่เหมาะสมตามประเภทของ view โดยอัตโนมัติ สิ่งสำคัญที่ควรสังเกตคือ ใน async context self.get_response(request) จะคืนค่า awaitable ดังนั้นต้องใช้ await เสมอ หากลืม await จะได้รับ coroutine object แทน response ซึ่งเป็นข้อผิดพลาดที่พบบ่อยเมื่อเริ่มต้นเขียน async middleware
สำหรับ production ที่รันบน ASGI server อย่าง Daphne หรือ Uvicorn async middleware ช่วยให้ประมวลผล request ได้พร้อมกันหลายตัวบน event loop เดียว โดยไม่ต้องพึ่งพา thread pool เหมือน WSGI ซึ่งช่วยลด memory footprint และเพิ่ม throughput ได้อย่างมีนัยสำคัญ
พร้อมที่จะพิชิตการสัมภาษณ์ Django แล้วหรือยังครับ?
ฝึกฝนด้วยตัวจำลองแบบโต้ตอบ, flashcards และแบบทดสอบเทคนิคครับ
Django Signals: รูปแบบ Publish-Subscribe
Django signals เป็นกลไกที่ช่วยให้ component ที่แยกส่วนกันสามารถสื่อสารกันได้โดยไม่ต้องมีการเชื่อมต่อโดยตรง (loose coupling) เมื่อ model ถูกบันทึก ลบ หรือเมื่อ request เริ่มต้นหรือเสร็จสิ้น Django จะกระจาย signal ออกไปให้ receiver ที่ลงทะเบียนไว้จัดการ การแยกส่วนนี้ทำให้สามารถเพิ่ม logic ใหม่ได้โดยไม่ต้องแก้ไขโค้ดเดิม ซึ่งสอดคล้องกับ Open-Closed Principle
Signal ที่ถูกใช้บ่อยที่สุดในการสัมภาษณ์คือ pre_save, post_save, pre_delete และ post_delete จาก django.db.models.signals นอกจากนี้ยังมี request_started และ request_finished สำหรับ HTTP request lifecycle ผู้สมัครที่สามารถอธิบายได้ว่าควรใช้ signal ใดในสถานการณ์ใด จะได้รับคะแนนสูงในการสัมภาษณ์
การใช้ post_save สำหรับการสร้าง Profile อัตโนมัติ
Pattern คลาสสิกของ post_save คือการสร้าง object ที่เกี่ยวข้องเมื่อ model instance ถูกบันทึกเป็นครั้งแรก ตัวอย่างที่พบบ่อยที่สุดคือการสร้าง user profile อัตโนมัติเมื่อมีการสร้าง User ใหม่ แนวทางนี้ช่วยให้ User model สะอาด (clean) และมอบหมายความรับผิดชอบในการสร้าง profile ให้กับ signal layer โดยไม่ต้องแก้ไข User model โดยตรง
# apps/accounts/signals.py
from django.db.models.signals import post_save
from django.dispatch import receiver
from django.contrib.auth import get_user_model
from apps.accounts.models import UserProfile
User = get_user_model()
@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
# 'created' is True only on INSERT, False on UPDATE
if created:
UserProfile.objects.create(
user=instance,
display_name=instance.get_full_name() or instance.username,
)Parameter created แบบ boolean เป็นจุดสำคัญที่ช่วยแยกแยะระหว่าง record ใหม่ (INSERT) กับการอัปเดต record ที่มีอยู่แล้ว (UPDATE) การตรวจสอบ flag นี้ทุกครั้งจะป้องกันการสร้าง profile ซ้ำเมื่อมีการ save User instance ในภายหลัง ส่วน parameter **kwargs เป็นสิ่งจำเป็นสำหรับ signal receiver ทุกตัว เนื่องจาก Django อาจเพิ่ม keyword arguments ใหม่ในเวอร์ชันอนาคต การละเว้น **kwargs จะทำให้โค้ดเสียหายเมื่ออัปเกรด Django
การใช้ pre_save สำหรับ Data Validation และ Transformation
Signal pre_save ทำงานก่อนที่ Django จะเขียนข้อมูลลงฐานข้อมูล จึงเหมาะอย่างยิ่งสำหรับการแปลงข้อมูล (data transformation) ก่อนบันทึก ตัวอย่างที่แสดงด้านล่างคือการสร้าง URL slug อัตโนมัติจาก title ของบทความ พร้อมกลไกตรวจสอบความซ้ำกัน
# apps/blog/signals.py
from django.db.models.signals import pre_save
from django.dispatch import receiver
from django.utils.text import slugify
from apps.blog.models import Article
@receiver(pre_save, sender=Article)
def auto_generate_slug(sender, instance, **kwargs):
if not instance.slug:
base_slug = slugify(instance.title)
slug = base_slug
counter = 1
# Ensure slug uniqueness
while Article.objects.filter(slug=slug).exclude(pk=instance.pk).exists():
slug = f'{base_slug}-{counter}'
counter += 1
instance.slug = slugโค้ดนี้ตรวจสอบก่อนว่า slug ยังว่างอยู่หรือไม่ (if not instance.slug) เพื่อไม่ให้เขียนทับ slug ที่ผู้ใช้กำหนดเอง จากนั้นใช้ loop ตรวจสอบความซ้ำกัน โดย .exclude(pk=instance.pk) จะไม่นับ record ปัจจุบัน ทำให้ไม่เกิดปัญหาเมื่อ save record เดิมซ้ำ สิ่งที่ควรสังเกตคือการแก้ไข instance.slug โดยตรง จะส่งผลต่อข้อมูลที่ถูกเขียนลงฐานข้อมูล เนื่องจาก pre_save ทำงานก่อนคำสั่ง SQL INSERT/UPDATE
การลงทะเบียน Signal ใน AppConfig.ready()
แนวทางที่ Django แนะนำอย่างเป็นทางการสำหรับการลงทะเบียน signal คือการ import signal module ภายใน method AppConfig.ready() วิธีนี้รับประกันว่า signal receiver จะถูกเชื่อมต่อเพียงครั้งเดียว หลังจากที่ app registry โหลด model ทั้งหมดเรียบร้อยแล้ว ทำให้ไม่เกิดปัญหา AppRegistryNotReady หรือ signal ที่ลงทะเบียนซ้ำ
# apps/accounts/apps.py
from django.apps import AppConfig
class AccountsConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'apps.accounts'
def ready(self):
# Import signals module to register receivers
import apps.accounts.signals # noqa: F401Comment # noqa: F401 บอก linter ว่าการ import โดยไม่ใช้ตัวแปรนี้เป็นเรื่องตั้งใจ เนื่องจากจุดประสงค์ของ import คือการ execute module-level code ใน signals.py ซึ่งจะทำให้ decorator @receiver ทำงานและลงทะเบียน handler กับ signal ที่กำหนดไว้ หากไม่มีการ import นี้ signal receiver จะไม่ถูกเชื่อมต่อ และ logic ที่เขียนไว้จะไม่ทำงาน
การสร้าง Custom Signals สำหรับ Domain Events
นอกเหนือจาก built-in model signals แล้ว Django ยังรองรับการสร้าง custom signals สำหรับจัดการ domain-specific events เช่น การชำระเงินสำเร็จ การเปลี่ยนแปลงสถานะ subscription หรือการส่งการแจ้งเตือน การใช้ custom signal ช่วยแยก business logic ของแต่ละ domain ออกจากกัน ทำให้ระบบขยายตัวได้ง่ายโดยไม่ต้องแก้ไขโค้ดเดิม
# apps/orders/signals.py
from django.dispatch import Signal
# Define custom signals with documentation
order_completed = Signal() # Sent after payment confirmation
order_refunded = Signal() # Sent after refund processing
# apps/orders/services.py
from apps.orders.signals import order_completed
def complete_order(order):
order.status = 'completed'
order.save()
# Dispatch signal with relevant context
order_completed.send(
sender=order.__class__,
order=order,
total=order.total_amount,
)
# apps/notifications/receivers.py
from django.dispatch import receiver
from apps.orders.signals import order_completed
@receiver(order_completed)
def send_order_confirmation_email(sender, order, **kwargs):
# Email logic decoupled from order processing
from apps.notifications.services import send_email
send_email(
to=order.customer.email,
template='order_confirmation',
context={'order': order},
)ตัวอย่างนี้แสดงให้เห็นการแยกส่วนที่ชัดเจนระหว่างสาม module ได้แก่ orders/signals.py ที่ประกาศ signal, orders/services.py ที่ dispatch signal หลังจากประมวลผล order เสร็จ และ notifications/receivers.py ที่รับ signal และจัดการส่ง email โดยไม่ต้องรู้รายละเอียดของ order processing แนวทางนี้ทำให้สามารถเพิ่ม receiver ใหม่ในอนาคตได้ เช่น การส่ง push notification หรือการอัปเดต analytics โดยไม่ต้องแก้ไข complete_order function เลย
ข้อผิดพลาดที่พบบ่อยในการสัมภาษณ์เกี่ยวกับ Middleware และ Signals
Method QuerySet.update() และ bulk_create() ของ Django จะข้าม method save() ของ model ทั้งหมด ซึ่งหมายความว่า signal pre_save และ post_save จะไม่ถูกเรียกใช้งาน เช่นเดียวกับ delete() บน QuerySet เทียบกับการเรียก delete() บน model instance ตัวเดียว นี่เป็นหนึ่งในคำถามเกี่ยวกับ Django signal ที่ถูกถามบ่อยที่สุดในการสัมภาษณ์ การไม่ทราบข้อจำกัดนี้อาจทำให้ signal handler ที่เขียนไว้ถูกข้ามไปโดยไม่รู้ตัว
ข้อผิดพลาดอื่นที่พบบ่อยในระดับ senior interview มีดังนี้
- Circular imports ใน signals: การ import model ที่ระดับ module ใน signal files อาจทำให้เกิด error
AppRegistryNotReadyควร import ภายใน receiver function หรือใช้AppConfig.ready()เสมอ - การขาด
**kwargsใน receiver: การละเว้น**kwargsจาก signature ของ receiver function จะทำให้เกิดข้อผิดพลาดเมื่อ Django เพิ่ม parameter ใหม่ให้กับ signal ในอนาคต ซึ่งเป็นข้อกำหนดที่ผู้สมัครหลายคนมองข้าม - Logic หนักใน signal handlers: Signal ทำงานแบบ synchronous ภายใน database transaction เดียวกันโดยค่าเริ่มต้น หาก signal handler ทำงานหนัก เช่น เรียก external API หรือส่ง email โดยตรง จะทำให้ response time ของ view สูงขึ้น สำหรับ operation ที่ใช้เวลานานควร offload ไปยัง task queue เช่น Celery หรือ Django Q
- Middleware ที่แก้ไข response content: การเปลี่ยนแปลง
response.contentหลังจากที่ view ตั้งค่าไว้แล้ว อาจทำให้ streaming responses เสียหาย และทำให้Content-Lengthheader ไม่ตรงกับขนาดจริงของ response body - การลงทะเบียน signal ซ้ำ: หากใช้
connect()แทน decorator@receiverอาจเกิดกรณีที่ handler ถูกลงทะเบียนหลายครั้ง (เช่น เมื่อ Django reload module) การตั้งdispatch_uidจะป้องกันปัญหานี้ได้
Middleware กับ Signals: เมื่อใดควรใช้อะไร
การเลือกใช้ middleware หรือ signal ขึ้นอยู่กับลักษณะของงานที่ต้องการทำ ตารางด้านล่างสรุปการเปรียบเทียบที่ช่วยในการตัดสินใจ
| ประเด็น | Middleware | Signals | |---|---|---| | การแก้ไข request/response | ทำได้โดยตรง | ทำไม่ได้ | | Authentication และ authorization | เหมาะสมอย่างยิ่ง | ไม่เหมาะสม | | Model lifecycle hooks | ทำไม่ได้ | เหมาะสมอย่างยิ่ง | | Cross-cutting concerns (logging, timing) | เหมาะสมอย่างยิ่ง | ทำได้แต่ไม่เหมาะ | | Decoupled business logic | ไม่เหมาะสม | เหมาะสมอย่างยิ่ง | | Async support ใน Django 5.2 | รองรับเต็มรูปแบบ | รองรับเต็มรูปแบบ (asend/asend_robust) | | ขอบเขตการทำงาน | ทุก HTTP request | เหตุการณ์เฉพาะ (save, delete, custom) | | จุดเริ่มต้นการทำงาน | HTTP request เข้ามา | เหตุการณ์ถูก dispatch |
กฎทั่วไปคือ หากต้องการจัดการ HTTP request/response ให้ใช้ middleware หากต้องการตอบสนองต่อการเปลี่ยนแปลงของ model หรือ domain event ให้ใช้ signal การใช้ signal สำหรับ cross-cutting concern อย่าง logging ถึงแม้จะเป็นไปได้ แต่จะทำให้โค้ดซับซ้อนโดยไม่จำเป็น เนื่องจาก middleware ถูกออกแบบมาเพื่องานประเภทนี้โดยเฉพาะ
บทสรุป
ประเด็นสำคัญที่ควรจดจำสำหรับการสัมภาษณ์เชิงเทคนิคเกี่ยวกับ Django middleware และ signals มีดังนี้
- Django middleware สร้าง pipeline แบบหัวหอมที่ประมวลผล request จากบนลงล่างและ response จากล่างขึ้นบน โดย
self.get_response(request)คือจุดแบ่งระหว่างขั้นตอนก่อนและหลัง view ลำดับในsettings.MIDDLEWAREจึงมีผลต่อพฤติกรรมของระบบโดยตรง - Custom middleware เหมาะสำหรับ cross-cutting concerns เช่น logging, timing, security headers, rate limiting และ request modification ที่ต้องทำงานกับทุก HTTP request
- Django 5.2 รองรับ async middleware อย่างเต็มรูปแบบผ่าน
async_capableflag และ async__call__method ช่วยให้จัดการ I/O-bound operations ได้โดยไม่บล็อก event loop สำหรับแอปพลิเคชันที่รันบน ASGI server - Signal
post_saveและpre_saveจัดการ model lifecycle events โดยpre_saveเหมาะสำหรับการแปลงข้อมูลก่อนเขียนลงฐานข้อมูล ส่วนpost_saveเหมาะสำหรับการสร้าง related objects และส่งการแจ้งเตือน QuerySet.update(),bulk_create()และQuerySet.delete()ข้าม signal ทั้งหมด ซึ่งเป็นข้อจำกัดที่ถูกถามบ่อยที่สุดในการสัมภาษณ์เกี่ยวกับ Django signals- ควรลงทะเบียน signal ใน
AppConfig.ready()เสมอ เพื่อรับประกันว่า handler จะถูกเชื่อมต่อเพียงครั้งเดียวหลังจากโหลด model ทั้งหมดแล้ว - Custom signals ช่วยแยก domain events ออกจาก business logic หลัก ทำให้ระบบขยายตัวได้ง่ายตามหลัก Open-Closed Principle โดยไม่ต้องแก้ไขโค้ดเดิม
เริ่มฝึกซ้อมเลย!
ทดสอบความรู้ของคุณด้วยตัวจำลองสัมภาษณ์และแบบทดสอบเทคนิคครับ
แท็ก
แชร์
บทความที่เกี่ยวข้อง

คำถามสัมภาษณ์งาน Django: ORM, Middleware และ DRF เจาะลึก
คำถามสัมภาษณ์งาน Django ครอบคลุมการปรับแต่ง ORM ด้วย select_related และ prefetch_related, สถาปัตยกรรม middleware, ประสิทธิภาพ serializer ของ Django REST Framework, permissions และรูปแบบ pagination

คำถามสัมภาษณ์งาน Django และ Python: 25 คำถามยอดนิยมประจำปี 2026
25 คำถามสัมภาษณ์งาน Django และ Python ที่พบบ่อยที่สุด ORM, views, middleware, DRF, signals และการปรับแต่งประสิทธิภาพ พร้อมคำตอบละเอียดและตัวอย่างโค้ด

Django ORM: เพิ่มประสิทธิภาพคิวรีให้ทำงานเต็มขีดความสามารถ
คู่มือฉบับสมบูรณ์สำหรับเพิ่มประสิทธิภาพคิวรีของ Django ORM ทั้ง select_related, prefetch_related, ดัชนี การวิเคราะห์ปัญหา N+1 และเทคนิคขั้นสูงสำหรับแอปพลิเคชันที่ต้องการประสิทธิภาพสูง