Programming

Django Template

The Django template language
เกี่ยวกับเอกสารนี้
เอกสารนี้อธิบายรายละเอียดเกี่ยวกับไวยากรณ์ของ Django Template . หรือมีข้อสงสัยหรือปัญหาฝนการใช้งาน โปรดอ่าน The Django template language: For Python programmers.
Django template นั้นออกแบบมาอย่างสมดุลระหว่างความสามารถและความง่ายดาย. มันถูกออกแบบมาให้สามารถทำงานกับ HTML ได้สะดวก นั่นรวมถึง Text-Based อื่นๆด้วย.
หลักการ
ถ้าคุณเคยมีพื้นฐานการเขียนโปรแกรมที่ฝังโค้ดใน HTML แล้ว คุณจะรู้สึกเหมือนได้กลับบ้านอีกครั้ง การใช้ Django template จะเป็นอะไรที่ง่ายดาย แต่ถ้าหากคุณหวังว่าจะเห็นโค้ด Python ใน Django template แล้ว ต้องขอแสดงความเสียใจที่ทำให้ผิดหวัง
The Django template มีฟังชั่นเหมือนกับภาษาโปรแกรมทั่วไป มี if tags เพื่อตรวจสอบเงื่อนไข มี for loop เอาไว้วนให้ปวดหัวเล่น Django template จะรันเพียง template tag และจะไม่รัน Python code โดยเด็ดขาด (c9jgiklk,ki5desof ะฟเ grbj,g9b,wfh)
Templates
Template เป็นเพียงไฟล์ text  สามารถสร้างในรูปแบบใดก็ได้ (HTML, XML, CSV, etc.).
มันจะประกอปด้วย ตัวแปร, ที่จะถูกแทนที่เมื่อ template ถูกสร้างขึ้นมา และยังมี tags ที่ทำหน้าที่ควบคุม.
ข้างล่างนี่คือตัวอย่างง่ายๆ
{% extends “base_generic.html” %}
{% block title %}{{ section.title }}{% endblock %}
{% block content %}
<h1>{{ section.title }}</h1>
{% for story in story_list %}
<h2>
<a href=”{{ story.get_absolute_url }}”>
{{ story.headline|upper }}
</a>
</h2>
<p>{{ story.tease|truncatewords:”100″ }}</p>
{% endfor %}
{% endblock %}
Variables
ตัวแปรจะมีหน้าตาประมาณนี้: {{ variable }}. เมื่อ template เจอตัวแปรนี้ จะแทนที่ตัวแปรด้วยค่าที่ได้รับมา
ใช้จุดคั่นตัวแปร (.) เพื่อเข้าถึงแอททริบิวต์ในตัวแปร.
ยกตัวอย่างเช่น, {{ section.title }} จะถูกแทนที่ด้วยค่า title ซึ่งเป็นแอททริบิวต์ของออปเจ็กต์ section.
ถ้าไม่ได้กำหนดค่าให้ หรือไม่พบตัวแปร มันจะถูกแทนที่ด้วย TEMPLATE_STRING_IF_INVALID ซึ่งโดยปกติจะเป็น” (สตริงว่าง) โดยปริยาย.
Filters
คุณสามารถแก้ไขตัวแปรสำหรับการแสดงผลโดยการใช้ ตัวกรอง.
Filters จะมีหน้าตาแบบนี้: {{ name|lower }} จะแสดงค่าของ name เป็นตัวอักษรแบบพิมพ์เล็ก
ฟิลเตอร์สามารถรวมกันหลายๆอันได้แบบนี้. {{ text|escape|linebreaks }} ฟิลเตอร์นี้จะแปลง text เป็น escape character แล้วค่อยใส่ <p> tags เข้าไปภายหลัง.
ฟิลเตอร์บางตัวจะมีอาร์กิวเมนต์ เช่น : {{ bio|truncatewords:30 }}. อันนี้จะแสดง 30 ตัวอักษรแรกของ bio เป็นต้น
ฟิลเตอร์ที่ถายในมีช่องว่างต้องเติมลูกน้ำ(”); ตัวอย่างเช่น {{ list|join:”, ” }}.
default
ฟิลเตอร์นี้จะแสดงค่าปริยายที่เรากำหนด หากตัวแปรไม่มีค่า
เช่น:
{{ value|default:”nothing” }}
ถ้า value ไม่มีค่าอะไรจะแสดง “nothing”.
length
จะแสดงความยาวของตัวแปร ใช้ได้ทั้ง list และ string ;
เช่น:
{{ value|length }}
ถ้า value เป็น [‘a’, ‘b’, ‘c’, ‘d’], output จะเป็น 4.
Tags
Tags จะหน้าตาแบบนี้: {% tag %}. Tags จะซับซ้อนกว่าตัวแปรนิดนึง: tag บางอย่างจะสร้่าง text outpu. Tag บางอย่างให้ควบคุมโปรแกรม
tag ส่วนมาต้องมีจุดเริ่มต้นและจุดจบ (i.e. {% tag %} … tag contents … {% endtag %}).
for
tag นี้เอาไว้สร้าง loop ซึงแปลว่าloop ก็คือ loop ไม่รู้จะอธิบายยังไง – -” ดูตัวอย่างอาจจะหายงง
athlete_list:
<ul>
{% for athlete in athlete_list %}
<li>{{ athlete.name }}</li>
{% endfor %}
</ul>
if and else
อันนี้คือ if else ธรรมดามาก มีทุกภาษา แต่ Django จะทะลึ่งนิดนึง คือจะไม่เปรียบเทียบกับอะไรเลย จะตรวจที่ตัวแปรเลยว่ามีค่า “True” หรือเปล่า ถ้าไม่มีก็ข้ามไป **ระวัง ถ้า value มีอะไรอยู่ข้างใน tag  นี้จะมองเป็น “True” เสมอ ยกเว้นมันมีค่า “False” **
{% if athlete_list %}
Number of athletes: {{ athlete_list|length }}
{% else %}
No athletes.
{% endif %}
จากตัวอย่างข้างบน , ถ้า athlete_list ไม่ว่างหรือไม่ใช่ “False ” จะแสดง {{ athlete_list|length }}.
ifequal และ ifnotequal
แสดงบางอย่างถ้าอากิวเมนต์ทั้งสองตัวเท่ากัน.
ลองดูตัวอย่าง:
{% ifequal athlete.name coach.name %}

{% endifequal %}
หรือ:
{% ifnotequal athlete.name “Joe” %}

{% endifnotequal %}
block และ extends
สร้าง template inheritance (อ่านด้านล่าง), ช่วยให้งานง่ายขึ้นเยอะ เราสามารถแบ่ง template เป็นชิ้นย่อยๆได้.
Comments
คอมเม้นในโปรแกรม คงไม่ต้องอธิบายกันให้มากความ: {# #}.
ตัวอย่าง, template  นี้จะแสดง ‘hello’:
{# greeting #}hello
น่าเสียดายว่ามันใช้ได้บรรทัดเดียว หากขี้เกียจกดหลายทีให้ใช้ {% comment %} และ {% endcomment %}
Template inheritance
ไม่ต้องประหลาดใจว่า “เทมเพลตมรดก” (ลองดู google translate แล้วจะพบว่ามีฮากว่านี้) คืออะไร มันคือการสืบทอดคุณสมบัติของเทมเพลต มันสามารถช่วยจัดการสร้างโครงสร้างของหน้าเว็บ ด้วยการใช้ tag {%block name%}…{%endblock%} คุณมาสามารถเพิ่มเติมอะไรก็ได้ตรงกลางระหว่าง block
เพื่อให้ง่ายต่อการเข้าใจเทมเพลทมรดกโดยเริ่มต้นด้วยตัวอย่าง:
<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN”
“http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>
<html xmlns=”http://www.w3.org/1999/xhtml” xml:lang=”en” lang=”en”>
<head>
<link rel=”stylesheet” href=”style.css” />
<title>{% block title %}My amazing site{% endblock %}</title>
</head>
<body>
<div id=”sidebar”>
{% block sidebar %}
<ul>
<li><a href=”/”>Home</a></li>
<li><a href=”/blog/”>Blog</a></li>
</ul>
{% endblock %}
</div>
<div id=”content”>
{% block content %}{% endblock %}
</div>
</body>
</html>
เราสร้าง template นี้โดยใช้ชื่อว่า base.html, เป็นโครงร่าง HTML ง่ายๆ แล้วเราค่อยสร้าง template’s ต่อมาโดยการสืบทอด template’s นี้
ในตัวอย่างนี้, {% block %} กำหนด block ของ child template’s ไว้สามอัน เราสามารถเพิ่มเติมได้โดยยังคงโครงสร้างของ template เดิมไว้
child template อาจจะหน้าตาแบบนี้:
{% extends “base.html” %}
{% block title %}My amazing blog{% endblock %}
{% block content %}
{% for entry in blog_entries %}
<h2>{{ entry.title }}</h2>
<p>{{ entry.body }}</p>
{% endfor %}
{% endblock %}
{% extends %} tag คือกุญแจไปสู้ห้องแห่งความลับ. แฮรี่ พอตเตอร์บอกว่าเราสารถใช้ {% extends %} เพื่อสืบทอดทุก template ได้ มหัศจรรย์จริงๆ!! เคราเมอร์ลินเป็นพยาน
สังเกต {% block %} tags ใน base.html and ให้ดีๆ มันจะถูกแทนที่ด้วยข้อมูลใน child template. output ออกมาหน้าตาประมาณนี้:
<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN”
“http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>
<html xmlns=”http://www.w3.org/1999/xhtml” xml:lang=”en” lang=”en”>
<head>
<link rel=”stylesheet” href=”style.css” />
<title>My amazing blog</title>
</head>
<body>
<div id=”sidebar”>
<ul>
<li><a href=”/”>Home</a></li>
<li><a href=”/blog/”>Blog</a></li>
</ul>
</div>
<div id=”content”>
<h2>Entry one</h2>
<p>This is my first entry.</p>
<h2>Entry two</h2>
<p>This is my second entry.</p>
</div>
</body>
</html>
เราไม่ได้กำหนด sidebar block ใน child template ,ข้อมูลใน {% block %} tag จะใช้ค่าเดิมใน base.html
เราสามารถสืบทอด template’s หลายๆชั้นเท่าที่ต้องการเช่น :
สร้าง base.html เป็น templat  ที่เป็นหน้าตาหลักของ site
สร้าง base_SECTIONNAME.html สำหรับทุกๆส่วนย่อย. เช่น, base_news.html, base_sports.html. โดยสืบทอดมาจาก base.html นั่นรวมถึง styles/design.
สร้าง template’s ตามมาอย่างใจต้องการ news blog ect.
สะดวกและง่ายดาย ประหยัดโค้ด.
นี่เป็นเคล็ดลับเล็กๆน้อยๆในการสืบทอด template’s :
ถ้าคุณใช้ {% extends %} มันจะต้องเป็น tag แรกใน template’s นั้น
เราสามารใส่ {% block %} tags ใน base template เท่าไรก็ได้ และเรายังสามารถเพิ่มเติมมันใน child template’s ภายหลัง
ถ้าเจอเนื้อหาซ้ำๆกัน, เป็นไปได้ว่าคุณย้ายมันไปไว้ใน parent template หรือเปล่า.
เพื่อให้อ่านง่าย กำหนดชื่อใน {% endblock %} tag. เช่น:
{% block content %}

{% endblock content %}
ด้วยเทคนิคนี้ ทำให้มั่นใจได้ว่า {% block %} tags ถูกปิดเรียบร้อยแล้ว.
สุดท้ายนี้, คุณไม่สามารถกำหนด {% block %} tags ที่มีชื่อเหมือนกันใน template’s เดียวกันได้เพราะนอกจากคุณจะงงแล้ว โปรแกรมก็จะงงด้วย.
Automatic HTML escaping
เวลาที่สร้าง HTML จาก templates, มันมีความเสียงที่จะพบตัวอักษรที่ส่งผลให้การแสดงผล HTML ผิดพลาด. ลองดูตัวอยางจากโค้ดด้านล่างนี้:
Hello, {{ name }}.
ดูเหมือนจะปลอดภัย แต่จะเกิดอะไรขึ้นถ้า user กรอกข้อมูลต่อไปนี้:
<script>alert(‘hello’)</script>
ด้วย username นี้ มันจะถูกเรนเดอร์เป็น:
Hello, <script>alert(‘hello’)</script>
…งานเข้า!! pop-up a JavaScript alert box!
ต่อมา จะเป็นอย่างไรถ้า user ใช้ตัวอักษร ‘<‘ อย่างนี้?
<b>username
template’s ก็จะออกมาแบบนี้ :
Hello, <b>username
…งานเข้าอีกแล้ว!! ซวยแล้ว ตัวหนาทั้งเว็บ!
ไม่ดีแน่อย่างนี้ เพราะว่าผู้ไม่ประสงค์ดีบางคนอาจจะให้ช่องโหว่นี้ทำอันตรายต่อระบบได้. นี่เป็นช่องโหว่ของระบบรักษาความปลอดภัยที่เรียกว่าการโจมตีแบบ  Cross Site Scripting (XSS) .
เพื่อแก้ปัญหานี้ เรามีอยู่สองทางเลือก:
อย่างแรก คุณสามารถมั่นใจว่าจะมาสารถแสดงผลข้อมูลเหล่านี้ด้วย escape filter (อ่านด้านล่าง), ด้วยวิธีนี้ คุณสามารถมั่นใจว่าข้อมูลทุกอย่างที่แสดงผล ถูกแปลงไปเป็นข้อมูลที่ปลอดภัย
หรืออีกวิธี, ใช้ความสามารถของ Django ให้เป็นประโยชน์ เราสามารถทำ auto-escaping
โดยทั่วไปแล้ในDjango, ในทุกๆ template จะเปี่ยนให้โดยอัตโนมัติ เช่น:
< เปลี่ยนเป็น &lt;
> เปลี่ยนเป็น &gt;
‘ (single quote) เปลี่ยนเป็น &#39;
” (double quote) เปลี่ยนเป็น &quot;
& เปลี่ยนเป็น &amp;
ย้ำอีกครั้ง, auto-escaping เป็นไปโดยอัตโนมัติ เมื่อคุณเลือก Django คุณจะได้รับการปกป้อง.
แล้วจะปิดยังไง
ถ้าคุณไม่ต้องการใช้งาน  auto-escaped ทั้ง site บาง template หรือตัวแปรบางตัว คุณมาสามารถเลือกปิดได้ตามใจ
ทำไมถึงอยากจะปิดล่ะ? เพราะบางบางที คุณอาจจะต้องการเรนเดอร์ HTML โค้ด,ในกรณีนี้ คุณคงไม่ต้องการ escaped charector. ยกตัวอย่างเช่น บางทีคุณเก็น blob ของ HTML ในฐานข้อมูล และต้องการแสดงผลข้อูลนั้นลงบน template’s  โดยตรง. หรือบางทีคุณอาจจะใช้ Django’s template จัดการ text ที่ไม่ใช่ HTML – อย่างเชน e-mail
สำหรับตัวแปรเป็นตัวๆไป
เพื่อยกเลิก auto-escaping สำหรับตัวแปรแต่ละตัวโดยใช้ safe filter:
อันนี้จะแปลงตัวอักษร: {{ data }}
อันนี้จะไม่แปลงตัวอักษร: {{ data|safe }}
ลองดูตัวอย่างง่ายๆ data มีค่าเป็น'<b>’:
อันนี้จะแปลงตัวอักษร: &lt;b&gt;
อันนี้จะไม่แปลงตัวอักษร: <b>
สำหรับ template blocks
เพื่อจะควบคุม auto-escaping สำหรับ template, หมายถึงทั้ง template’s ใช้  autoescape tag, อย่างนี้:
{% autoescape off %}
Hello {{ name }}
{% endautoescape %}
autoescape tag สามารถเปลี่ยนแปลงได้โดยการเปลี่ยนค่า on หรือ off ในอาร์กิวเมนต์. ลองดูตัวอย่างนี้จะทำความเข้าใจได้ง่ายขึ้น:
โดยปกติแล้ว Auto-escaping จะถูกตั้งค่าเป็น on. Hello {{ name }}
{% autoescape off %}
This will not be auto-escaped: {{ data }}.
Nor this: {{ other_data }}
{% autoescape on %}
Auto-escaping applies again: {{ name }}
{% endautoescape %}
{% endautoescape %}
auto-escaping tag จะทำงานทั้งหน้า รวมไปถึงส่วน include tag,ตัวอย่างเช่น:
# base.html
{% autoescape off %}
<h1>{% block title %}{% endblock %}</h1>
{% block content %}
{% endblock %}
{% endautoescape %}
# child.html
{% extends “base.html” %}
{% block title %}This & that{% endblock %}
{% block content %}{{ greeting }}{% endblock %}
เพราะว่า auto-escaping ถูกปิดอยู่ในbase template, เพราะฉะนั้นมันจึงถูกปิดใน child template ด้วยเช่นเดียวกัน, ผลการรันHTML เมื่อตัวแปรgreeting เป็นอย่างนี้
<b>Hello!</b>:
<h1>This & that</h1>
<b>Hello!</b>
Notes
โดยปกติแล้ว Designer ไม่ต้องสนใจส่วนนี้มากเท่าใดนัก ปล่อยให้เป็นงานของ Developer (ไอ้คนที่เขียนโค้ดบน Pythion นั่นแหละ)เป็นคนคิดว่าอะไรควรจัดการดีกว่า.
String literals and automatic escaping
บ่อยครั้งที่เราใช้อาร์กิวเมนต์ที่เป็น string ในฟิลเตอร์:
{{ data|default:”This is a string literal.” }}
ข้อมูลตรงนี้จะไม่ถูก autoescape.
หมายความว่าควรเขียนอย่างนี้
{{ data|default:”3 &lt; 2″ }}
…ไม่ใช่
{{ data|default:”3 < 2″ }}  <– บัดซบ อย่าเขียนอย่างนี้เด็ดขาด.
เรียบเรียงจาก
The Django template language : http://docs.djangoproject.com/en/dev/topics/templates/#topics-templates
แหล่งข้อมูลเพิ่มเติม
Thai django : http://www.django66.com/
PyThai google groups : http://groups.google.co.th/group/pythai
ติดต่อผม
Kowit Charoenratchatabhan [email protected]
Felspar Co.,Ltd.
This document is licensed under a Creative Commons Attribution-Non-Commercial-Share Alike 3.0 Unported License.

Leave a Reply

Your email address will not be published. Required fields are marked *

%d bloggers like this: