یک 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
| static | media | |
|---|---|---|
| منبع | توسعهدهنده (CSS، JS، فونت، لوگو) | کاربر (عکس محصول، فایل آپلودی) |
| تنظیمات | STATIC_URL، STATIC_ROOT، STATICFILES_DIRS | MEDIA_URL، MEDIA_ROOT |
| در git | بله | هرگز |
| در سرور | collectstatic + WhiteNoise یا nginx | nginx مستقیم |
| در قالب | {% 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 پیدا نشود خطا نمیدهد و فقط متغیر را خالی میگذارد؛ برای لینکهای اختیاری مفید است.