什麼是模板(Template)? Django的Template是如何工作的
Django的模板是靜態的html文件,它只決定了一個頁面的樣式或外觀。它需要視圖View傳遞過來的變量(Variable)或內容對象(Context object)才能被渲染成一個完整的頁面。這樣做的好處是實現了樣式與業務邏輯的分離,便於前端和後端Web開發人員各自完成自己的開發工作。
我們先來看一個新聞博客的例子。當用戶訪問/blog/article/2/的時候,URL路由器會調用視圖views.py的article_detail方法。article_detail所做的就是提取id=2的文章對象,通過render方法,將它傳遞到模板文件/blog/article_detail.html。
# blog/urls.py
from django.urls import path
from . import views
urlpatterns = [
path('blog/article/<int:id>/', views.article_detail, name='article_detail'),
]
# blog/views.py
from django.shortcuts import render, get_object_or_404
from .models import Article
def article_detail(request, id):
article = get_object_or_404(Article, pk=id)
return render(request, 'blog/article_detail.html', {"article": article})
下圖是模板文件blog/article_detail.html的代碼。在模板文件裏我們可以通過雙括號{{ article }} 顯示變量或內容對象,還可以通過點號(.)用來直接訪問變量的屬性。
{% block content %}
{{ article.title }}
{{ article.pub_date }}
{{ article.body }}
{% endblock %}
模板(Template)文件的正確位置
對於html模板文件,我們建議放在app/templates/app/文件夾裏,而不是簡單放在app/templates/裏。看似我們多加了一層文件夾使問題複雜化了,但這樣做實際上更安全。這與Django查找模板文件的方法有關。因爲我們多加了一層app,這樣Django只會查找app文件夾裏的模板文件。在views.py裏我們也建議通過app/template_name.html調用template,這樣會杜絕與其它同名template的衝突。更多內容見【Django項目文件與文件夾的合理佈局】
模板過濾器Filter
您可以通過使用過濾器來改變變量在模板中的顯示。比如{{ article.title | lower }} 中lower過濾器可以讓文章的標題轉化爲小寫。Django的模板提供了許多內置過濾器,你可以直接使用,非常方便。
下面是一些Django模板常用過濾器。
過濾器 | 例子 |
lower, upper | {{ article.title | lower }} 大小寫 |
length | {{ name | length }} 長度 |
default | {{ value | default: "0" }} 默認值 |
date | {{ picture.date | date:"Y-m-j" }} 日期格式 |
dicsort | {{ value | dicsort: "name" }} 字典排序 |
escape | {{ title | escape }} 轉義 |
filesizeformat | {{ file | filesizeformat }} 文件大小 |
first, last | {{ list | first }} 首或尾 |
floatformat | {{ value | floatformat }} 浮點格式 |
get_digit | {{ value | get_digit }} 位數 |
join | {{ list | join: "," }} 字符連接 |
make_list | {{ value | make_list }} 轉字符串 |
pluralize | {{ number | pluralize }} 複數 |
random | {{ list | random }} 隨機 |
slice | {{ list | slice: ":2" }} 切 |
slugify | {{ title | slugify }} 轉爲slug |
striptags | {{ body | striptags }} 去除tags |
time | {{ value | time: "H:i" }} 時間格式 |
timesince | {{ pub_date | timesince: given_date }} |
truncatechars | {{ title | truncatechars: 10 }} |
truncatewords | {{ title | truncatewords: 2 }} |
truncatechars_html | {{ title | truncatechars_html: 2 }} |
urlencode | {{ path | urlencode }} URL轉義 |
wordcount | {{ body | wordcount }} 單詞字數 |
模板標籤Tags
在Django模板裏,變量是放在雙括號{{ }}裏的,而代碼是放在{% tag_name %}標籤裏的。Django裏有很多自帶標籤,可以滿足絕大部分開發需求。
標籤Tags | 例子 |
{% block %} | {% block content %} 代碼塊 {% endblock %} |
{% csrf_token %} | {% csrf_token %} 表單專用 |
{% for %} | <ul>
{% for athlete in athlete_list %}
<li>{{ athlete.name }}</li>
{% endfor %}
</ul> |
{% for .. empty %} | <ul>
{% for athlete in athlete_list %}
<li>{{ athlete.name }}</li>
{% empty %}
<li>Sorry, no athletes。</li>
{% endfor %}
</ul> |
{% if %} | {% if title != "python" %}
Not python.
{% endif %}
{% if "hello" in greetings %}
Say hello
{% endif %} |
{% url %} | {% url 'blog:article_detail' article.id %} |
{% now %} | {% now "jS F Y H:i" %} |
{% with %} | {% with total=business.employees.count %}
{{ total }} employee{{ total|pluralize }}
{% endwith %} |
{% load %} | # load tags and filters
{% load sometags library %} |
{% include %} | {% include "header.html" %} |
{% extends %} | {% extends "base.html" %} |
模板的繼承
Django支持模板的繼承。你需要使用extends標籤。在下面經典模板繼承案例中,template.html中的content模塊,會替換掉base.html中的content模塊。同時template.html繼承了base.html的sidebar和footer模塊。
# base.html
{% block sidebar %}
{% endblock %}
{% block content %}
{% endblock %}
{% block footer %}
{% endblock %}
# template.html
{% extends "base.html" %}
{% block content %}
{{ some code }}
{% endblock }
模板文件base.html的位置
extends標籤支持相對路徑,這就意味着當文件夾結構如下所示時:
dir1/
template.html
base2.html
my/
base3.html
base1.html
模板template.html中以下繼承方式都是可以的。
{% extends "./base2.html" %}
{% extends "../base1.html" %}
{% extends "./my/base3.html" %}
模板文件加載靜態文件
要在模板文件里加載靜態文件如css文件和js文件,你一共有三步要走:
第一步: 先在你的app下新建一個static文件夾,然後把你需要靜態文件放進去,推薦路徑app/static/app/custom.css。
第二步: 在myproject/settings.py增加靜態文件設置靜態文件STATIC_URL。
STATIC_URL = '/static/'
第三步:在你的模板裏使用{% load static %},如下所示。
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<title>{% block title %} Django Web Applications {% endblock %} </title>
<link rel="stylesheet" href="{% static 'app/custom.css' %}">
</head>
如果你需要使用的靜態文件不屬於某個app,而屬於整個項目project,那麼你還可以定義靜態文件文件夾列表。假設屬於整個項目的靜態文件放在/var/www/static/裏,那麼myproject/settings.py可以加入下面一行代碼。
STATICFILES_DIRS = [
os.path.join(BASE_DIR, "static"),
'/var/www/static/',
]