فصل ۴: View، URL و Template

قالب‌ها: وراثت، include، context processor، static و media، messages

یک base.html، صدها صفحه

زبان قالب جنگو عمداً محدود است: منطق کسب‌وکار جایش در View و مدل است و قالب فقط نمایش می‌دهد. قدرت اصلی آن وراثت است: یک اسکلت پایه با بلوک‌های قابل‌بازنویسی و صفحه‌هایی که فقط بلوک‌های لازم را پر می‌کنند.

{# templates/base.html #}
{% load static %}
<!DOCTYPE html>
<html lang="fa" dir="rtl">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>{% block title %}{{ site_name }}{% endblock %}</title>
  <link rel="stylesheet" href="{% static 'css/vazirmatn.css' %}">
  <link rel="stylesheet" href="{% static 'css/main.css' %}">
</head>
<body>
  {% include "partials/navbar.html" %}
  {% for message in messages %}
    <div class="alert alert-{{ message.tags }}">{{ message }}</div>
  {% endfor %}
  <main>{% block content %}{% endblock %}</main>
  {% block scripts %}{% endblock %}
</body>
</html>

{# templates/orders/detail.html #}
{% extends "base.html" %}
{% block title %}سفارش {{ order.tracking_code }} | {{ block.super }}{% endblock %}
{% block content %}
  <h1>سفارش {{ order.tracking_code }}</h1>
  <p>وضعیت: {{ order.get_status_display }}</p>
  {% include "orders/_items_table.html" with items=order.items.all only %}
{% endblock %}

context processor: داده‌ای که همه‌ی صفحه‌ها لازم دارند

نام سایت، تعداد اقلام سبد یا شماره‌ی پشتیبانی را نباید در هر View به context اضافه کرد. یک تابع ساده بنویسید و در TEMPLATES["OPTIONS"]["context_processors"] ثبت کنید:

# apps/core/context_processors.py
from django.conf import settings

def site(request):
    return {
        "site_name": "فرش کاشان",
        "support_phone": settings.SUPPORT_PHONE,
    }

static در برابر media

staticmedia
منبعتوسعه‌دهنده (CSS، JS، فونت، لوگو)کاربر (عکس محصول، فایل آپلودی)
تنظیماتSTATIC_URL، STATIC_ROOT، STATICFILES_DIRSMEDIA_URL، MEDIA_ROOT
در gitبلههرگز
در سرورcollectstatic + WhiteNoise یا nginxnginx مستقیم
در قالب{% static 'css/main.css' %}{{ carpet.image.url }}

نکته‌هایی که کمتر کسی می‌داند

  • {% include ... with x=1 only %} قالب فرعی را فقط با همان متغیرها رندر می‌کند؛ هم سریع‌تر است هم جلوی وابستگی پنهان به متغیرهای صفحه‌ی مادر را می‌گیرد.
  • جنگو همه‌ی متغیرها را خودکار escape می‌کند؛ فیلتر |safe روی داده‌ی کاربر یعنی باز کردن در XSS. اگر HTML کاربر لازم است، قبل از ذخیره با یک sanitizer مثل nh3 پاکش کنید.
  • context processorها برای هر رندر اجرا می‌شوند؛ کوئری سنگین در آن‌ها همه‌ی صفحات را کند می‌کند. یا کش کنید یا یک تابع lazy برگردانید که فقط در صورت استفاده اجرا شود.
  • با گذاشتن "string_if_invalid": "!!%s!!" در OPTIONS قالب (فقط در توسعه) متغیرهای غلط‌املایی به‌جای رشته‌ی خالی با علامت دیده می‌شوند.
  • تگ {% url 'orders:list' as list_url %} اگر url پیدا نشود خطا نمی‌دهد و فقط متغیر را خالی می‌گذارد؛ برای لینک‌های اختیاری مفید است.

برای ذخیره‌ی پیشرفت و شرکت در آزمون، وارد شوید — رایگان است.