DEV Community

Cover image for Django เลือก template มา render อย่างไร และทำไม Best Practice ถึงถูก
Sawit M.
Sawit M.

Posted on

Django เลือก template มา render อย่างไร และทำไม Best Practice ถึงถูก

จากการลองเล่น framework ตัวหนึ่งชื่อ Django (จังโก้) เพื่อนำมาใช้ในการทำ Web GUI สำหรับ project หนึ่ง

พอลองเล่นมาถึง Writing your first Django app, part 3 เกิดงงเรื่อง directory structure ของ template ที่ต้องเป็น project_name/app_name/templates/app_name/ และการสั่ง render template ต้องอ้างอิงชื่อเป็น app_name/home.html ซึ่งเค้าบอกว่าเป็น Best Practice

ที่ผมงงคือ... ทำไม directory structure ต้องมี app_name ซ้ำ 2 ครั้งเลยล่ะ ครั้งเดียวมันน่าจะรู้แล้วไหม และ ตอนเรียก template มา render ก็ต้องใส่ app_name ข้างหน้าชื่อ template อีก ซึ่งเราทำที่ app นี้อยู่แล้วทำไม่ยังต้องระบุอีกล่ะ

OK! ถ้ามันเป็น Best Practice ความไม่ make sense ต้องมีคำอธิบาย

มาดูกัน ผมเจออะไร (ต้องบอกก่อนว่าผมเพิ่งหัดใช้นะครับ เรื่องนี้หลายคนอาจรู้อยู่แล้ว 😁)

ใน settings.py ของ Django ที่เป็น "DjangoTemplate" จะเป็นแบบนี้

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

เราจะสนใจ 2 parameters นี้ก่อนคือ

  1. DIRS คือ path ที่เราต้องการให้ django ไปค้นหา เป็น list of strings (default = [])
  2. APP_DIRS คือ เป็น boolean บอกว่าให้หา template ใน directory ของ app หรือ ไม่ (default = True)

โดย พฤติกรรมในการหา template ของ "DjangoTemplate" จะเป็นลำดับตามนี้

  1. หาใน DIRS ก่อน โดยหาตามลำดับของ list ที่เรากำหนด
    เช่น DIRS = ['path/to/template1', 'path/to/template2', 'path/to/template3'] จะหาตามลำดับดังนี้

    /path/to/template1/
    /path/to/template2/
    /path/to/template3/

  2. หาใน APP_DIRS โดยถ้าเราตั้งค่าเป็น True Django จะไปดูจาก ตัวแปร INSTALLED_APPS ใน settings.py ซึ่ง เป็น list of string เช่น INSTALLED_APPS = ['app-a', 'app-b', 'app-c'] Django จะหาตามลำดับของ list นี้ ดังนี้

    /path/to/project/app-a/templates/
    /path/to/project/app-b/templates/
    /path/to/project/app-b/templates/

จากตัวอย่างข้างต้น ลำดับของ directory ที่ Django ใช้หา template คือ

/path/to/template1/
/path/to/template2/
/path/to/template3/
/path/to/project/app-a/templates/
/path/to/project/app-b/templates/ 👈 เราจะเขียน template ที่นี่
/path/to/project/app-b/templates/

ด้วย logic การทำงานแบบนี้ ถ้าเราเขียน template ที่ app-b ชื่อ home.html แล้วเราระบุ ชื่อ template ในการ render แค่ home.html ถ้าบังเอิญว่า app-a ก็มี home.html อยู่เช่นกัน มันจะไป render home.html ของ app-a แทน เพราะมันหาเจอก่อน

ด้วยพฤติกรรมการทำงานแบบนี้ เราจึงต้องทำตาม Best Practice โดยสร้าง sub directory ที่เป็นชื่อ app ใต้ directory templatate ของ app นั้นๆ ด้วย ดังนี้

/path/to/template1/
/path/to/template2/
/path/to/template3/
/path/to/project/app-a/templates/app-a/
/path/to/project/app-b/templates/app-b/ 👈 เราจะเขียน template ที่นี่
/path/to/project/app-b/templates/app-c/

และเวลาที่เราเรียก template มาใช้งานก็จะเรียกด้วยการระบุชื่อ template ดังนี้ app-b/home.html

ด้วยวิธีนี้ การ render จะไม่หยิบ template มาผิด app

Top comments (0)