~8 دقیقه مطالعه • بروزرسانی ۲۳ اسفند ۱۴۰۴
مقدمه
در بسیاری از پروژههای جنگو، نیاز داریم فیلدهای فرم را به صورت پویا و تکرارشونده نمایش دهیم. این کار باعث کاهش کدهای تکراری و افزایش انعطافپذیری قالبها میشود. جنگو با ارائه BoundField و متدهای کمکی، امکان کنترل کامل روی رندر فیلدها را فراهم میکند.
حلقهزدن روی فیلدهای فرم
اگر برای هر فیلد از HTML مشابهی استفاده میکنید، میتوانید با یک حلقه {% for %} کدهای تکراری را حذف کنید:
{% for field in form %}
<div class="fieldWrapper">
{{ field.errors }}
{{ field.label_tag }} {{ field }}
{% if field.help_text %}
<p class="help" id="{{ field.auto_id }}_helptext">
{{ field.help_text|safe }}
</p>
{% endif %}
</div>
{% endfor %}
ویژگیهای مهم BoundField
هر field در حلقه یک BoundField است و ویژگیهای مفیدی دارد:
field.errors: نمایش خطاهای اعتبارسنجی به صورت<ul class="errorlist">.field.field: دسترسی به شیء اصلیFieldو ویژگیهایی مانندmax_length.field.help_text: نمایش متن راهنما.field.html_name: نام HTML فیلد.field.id_for_label: شناسه HTML برای استفاده در<label>.field.is_hidden: تشخیص اینکه فیلد مخفی است یا نه.field.label: متن برچسب فیلد.field.label_tag: برچسب HTML کامل.field.legend_tag: مشابهlabel_tagاما با<legend>.field.use_fieldset: مشخص میکند آیا فیلد باید داخل<fieldset>قرار گیرد.field.value: مقدار فعلی فیلد.
استفاده از fieldset برای ویجتهای چندبخشی
اگر ویجت فیلد شامل چند ورودی باشد، میتوان آن را داخل fieldset قرار داد:
{% if field.use_fieldset %}
<fieldset>
{% if field.label %}{{ field.legend_tag }}{% endif %}
{% else %}
{% if field.label %}{{ field.label_tag }}{% endif %}
{% endif %}
{{ field }}
{% if field.use_fieldset %}</fieldset>{% endif %}
حلقهزدن روی فیلدهای مخفی و قابلمشاهده
برای مدیریت جداگانه فیلدهای مخفی و قابلمشاهده، جنگو دو متد ارائه میدهد:
hidden_fields()visible_fields()
نمونه:
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% for field in form.visible_fields %}
<div class="fieldWrapper">
{{ field.errors }}
{{ field.label_tag }} {{ field }}
</div>
{% endfor %}
رندر دستی فیلدها
برای کنترل کامل روی ظاهر فیلدها، میتوان آنها را به صورت دستی رندر کرد:
{{ form.non_field_errors }}
<div class="fieldWrapper">
{{ form.subject.errors }}
<label for="{{ form.subject.id_for_label }}">Email subject:</label>
{{ form.subject }}
</div>
نمایش خطاهای فرم
خطاهای هر فیلد با {{ field.errors }} نمایش داده میشوند:
<ul class="errorlist">
<li>Sender is required.</li>
</ul>
برای سفارشیسازی بیشتر:
{% if form.subject.errors %}
<ol>
{% for error in form.subject.errors %}
<li><strong>{{ error|escape }}</strong></li>
{% endfor %}
</ol>
{% endif %}
جمعبندی
حلقهزدن روی فیلدهای فرم، مدیریت فیلدهای مخفی و قابلمشاهده، استفاده از ویژگیهای BoundField و رندر دستی فیلدها از مهمترین قابلیتهای جنگو برای ساخت فرمهای حرفهای هستند. با این ابزارها میتوان قالبهایی انعطافپذیر، قابلتوسعه و کاملاً سفارشی ایجاد کرد.
مقدمه
جنگو از سیستم قدرتمندی برای مدیریت template engines استفاده میکند. این سیستم امکان استفاده از چندین موتور قالب، بارگذاری پویا، رندر قالبها و مدیریت خطاهای مرتبط با قالبها را فراهم میکند. تنظیمات مربوط به موتورهای قالب در بخش TEMPLATES قرار دارد.
پیکربندی موتورهای قالب
موتورهای قالب از طریق تنظیم TEMPLATES پیکربندی میشوند. این تنظیم یک لیست از دیکشنریهاست که هر کدام یک موتور قالب را تعریف میکنند:
TEMPLATES = [
{
"BACKEND": "django.template.backends.django.DjangoTemplates",
"DIRS": [],
"APP_DIRS": True,
"OPTIONS": {
# ...
},
},
]
مقدار BACKEND مسیر پایتونی کلاسی است که موتور قالب را پیادهسازی میکند. موتورهای داخلی شامل:
django.template.backends.django.DjangoTemplatesdjango.template.backends.jinja2.Jinja2
دو تنظیم مهم دیگر:
DIRS: مسیرهایی که موتور قالب باید در آنها به دنبال فایلهای قالب بگردد.APP_DIRS: مشخص میکند آیا قالبها از داخل اپلیکیشنها نیز بارگذاری شوند یا نه.
بارگذاری قالبها
ماژول django.template.loader دو تابع اصلی برای بارگذاری قالبها ارائه میدهد:
تابع get_template
این تابع قالبی با نام مشخص را بارگذاری میکند:
from django.template.loader import get_template
template = get_template("template.html")
اگر قالب پیدا نشود، خطای TemplateDoesNotExist و اگر قالب دارای خطای نحوی باشد، خطای TemplateSyntaxError رخ میدهد.
بارگذاری partial
در جنگو ۶.۰ امکان بارگذاری بخشهای خاص یک قالب با استفاده از # اضافه شده است:
partial = get_template("template.html#partial_name")
تابع select_template
این تابع لیستی از نامهای قالب را دریافت کرده و اولین قالب موجود را بارگذاری میکند:
template = select_template(["story_253_detail.html", "story_detail.html"])
مدیریت خطاهای قالب
دو استثنای مهم در هنگام بارگذاری قالبها:
TemplateDoesNotExist: زمانی که قالب پیدا نشود.TemplateSyntaxError: زمانی که قالب دارای خطای نحوی باشد.
رندر قالبها
تمام قالبهای بارگذاریشده دارای متد render() هستند:
template.render({"foo": "bar"})
اگر request ارسال شود، موتور قالب باید آن را در دسترس قرار دهد.
مثال الگوریتم جستجوی قالب
فرض کنید تنظیمات زیر را داریم:
TEMPLATES = [
{
"BACKEND": "django.template.backends.django.DjangoTemplates",
"DIRS": [
"/home/html/example.com",
"/home/html/default",
],
},
{
"BACKEND": "django.template.backends.jinja2.Jinja2",
"DIRS": [
"/home/html/jinja2",
],
},
]
اگر فراخوانی کنیم:
get_template("story_detail.html")
جنگو به ترتیب زیر جستجو میکند:
- /home/html/example.com/story_detail.html
- /home/html/default/story_detail.html
- /home/html/jinja2/story_detail.html
استفاده از render_to_string
برای کاهش تکرار در بارگذاری و رندر قالبها، تابع render_to_string ارائه شده است:
from django.template.loader import render_to_string
rendered = render_to_string("my_template.html", {"foo": "bar"})
جمعبندی
پیکربندی موتورهای قالب، بارگذاری قالبها، مدیریت خطاها و استفاده از توابعی مانند get_template و render_to_string از بخشهای مهم سیستم قالب در جنگو هستند. با درک این مفاهیم میتوان ساختار قالبها را بهینه، قابلمدیریت و انعطافپذیر طراحی کرد.
مقدمه
جنگو از یک سیستم قدرتمند برای مدیریت template engines استفاده میکند. این سیستم امکان استفاده از چندین موتور قالب، بارگذاری پویا، رندر قالبها و افزودن قابلیتهای سفارشی را فراهم میکند. موتورهای قالب از طریق django.template.engines قابل دسترسی هستند.
دسترسی به موتورهای قالب
برای دسترسی به موتورهای قالب پیکربندیشده:
from django.template import engines
django_engine = engines["django"]
template = django_engine.from_string("Hello {{ name }}!")
کلید 'django' همان مقدار NAME موتور قالب است.
موتورهای داخلی قالب
DjangoTemplates
برای استفاده از موتور قالب جنگو، مقدار BACKEND باید برابر باشد با:
"django.template.backends.django.DjangoTemplates"
اگر APP_DIRS=True باشد، موتور قالب به دنبال پوشه templates در اپلیکیشنهای نصبشده میگردد.
گزینههای قابل تنظیم در DjangoTemplates
autoescape: فعال یا غیرفعال کردن escape خودکار HTML (پیشفرض: True).context_processors: لیستی از توابعی که دادههای اضافی را به context اضافه میکنند.debug: فعالسازی حالت اشکالزدایی قالب.loaders: کلاسهای بارگذاریکننده قالب.string_if_invalid: مقدار خروجی برای متغیرهای نامعتبر.file_charset: کاراکترست فایلهای قالب (پیشفرض: utf‑8).libraries: ثبت کتابخانههای تگ سفارشی.builtins: افزودن کتابخانههای تگ به صورت پیشفرض.
موتور قالب Jinja2
برای استفاده از Jinja2 باید آن را نصب کنید:
pip install Jinja2
سپس مقدار BACKEND را تنظیم کنید:
"django.template.backends.jinja2.Jinja2"
گزینههای مهم Jinja2
مهمترین گزینه environment است که مسیر تابع سازنده محیط Jinja2 را مشخص میکند. جنگو به صورت خودکار مقادیر زیر را تنظیم میکند:
autoescape=Trueloaderبر اساس DIRS و APP_DIRSauto_reload=settings.DEBUGundefinedبر اساس حالت DEBUG
استفاده از context_processors در Jinja2
استفاده از context processor در Jinja2 توصیه نمیشود، زیرا Jinja2 امکان فراخوانی توابع با آرگومان را دارد. بهتر است توابع مورد نیاز را در env.globals قرار دهید.
مثال پیکربندی محیط Jinja2
from django.templatetags.static import static
from django.urls import reverse
from jinja2 import Environment
def environment(**options):
env = Environment(**options)
env.globals.update({
"static": static,
"url": reverse,
})
return env
نمونه استفاده در قالب Jinja2:
Admin
تفاوت تگها و فیلترها در Jinja2 و DTL
هر دو سیستم از تگها و فیلترها پشتیبانی میکنند، اما Jinja2 به دلیل امکان ارسال آرگومان به توابع، بسیاری از قابلیتها را سادهتر پیادهسازی میکند. همچنین Jinja2 دارای سیستم تستها است که در DTL وجود ندارد.
جمعبندی
جنگو با پشتیبانی از موتورهای قالب مختلف مانند DjangoTemplates و Jinja2 انعطافپذیری بالایی در رندر HTML فراهم میکند. با پیکربندی صحیح موتورهای قالب، استفاده از گزینههای پیشرفته و افزودن کتابخانههای سفارشی، میتوان سیستم قالبسازی پروژه را قدرتمند، قابلگسترش و کاملاً سفارشیسازیشده طراحی کرد.
نوشته و پژوهش شده توسط دکتر شاهین صیامی