Django学习纪录 15.模板进阶技巧[含static静态档使用方式]

之前有在用Django写一些小网站,现在暑假想说再来複习一下之前买的这本书
http://img2.58codes.com/2024/20118889bj9fH1vhuR.jpg
于是我就把它写成一系列的文章,也方便查语法
而且因为这本书大概是2014年出的,如今Django也已经出到2.多版
有些内容也变得不再支援或适用,而且语法或许也改变了
所以我会以最新版的Python和Django来修正这本书的内容跟程式码

目录:django系列文章-Django学习纪录

15. 模板进阶技巧

15.1 主题1-重複利用模板

DRY(don't repeat yourself,不要重複你自己)
WET(write everything twice,什么事都写两次)
这小节要用django好好地来重複利用已经写过的模板

15.1.1 汇入模板

使用{% include %}
index.html

<html>    <head>        <title>Index</title>        <meta charset="utf-8">    </head>    <body>        <h2>欢迎来到餐厅王</h2>        <p><a href="/accounts/register/">注册</a></p>        {% if request.user.is_authenticated %}            <p>                {{request.user}} 您已经登入啰~                <a href="/accounts/logout/">登出</a>            </p>            <a href="/restaurants_list/">餐厅列表</a>        {% else %}            <p>您尚未登入喔~<a href="/accounts/login/">登入</a></p>        {% endif %}    </body></html>

可以拆解为
index.html

<html>    <head>        <title>Index</title>        <meta charset="utf-8">    </head>    <body>        {% include 'body.html' %}    </body></html>


body.html

<h2>欢迎来到餐厅王</h2><p><a href="/accounts/register/">注册</a></p>    {% if request.user.is_authenticated %}        <p>            {{request.user}} 您已经登入啰~            <a href="/accounts/logout/">登出</a>        </p>        <a href="/restaurants_list/">餐厅列表</a>    {% else %}        <p>您尚未登入喔~<a href="/accounts/login/">登入</a></p>    {% endif %}

include的用法{% include '模版名称(路径)' %}

15.1.2 模板继承

不过其实include有时候没那么好用
一个页面可能需要花上好几个html档,且档案零碎
这时会非常痛苦!
那么就要改用模板的继承了
首先制定一个基础的模板
base.html

<!doctype html><html>    <head>        <title>{% block title %}{% endblock %}</title>    </head>    <body>        网页选单        <h1>{% block pagetitle %}{% endblock %}</h1>        <h1>说明</h1>        <p>{% block content %}{% endblock %}</p>        页尾    </body></html>

在每个需要自定义的地方,使用模板区块
一个模板区块以{% block BLOCKNAME %}为开头,以{% endblock %}为结尾
可以填入内容也可以留白,这个区块的内容会让继承此基础模板的子模板覆写,这与物件导向中关于类别的继承与覆写很类似
接着使用{% extends %}标籤让子模板去继承基础模板
final.html

{% extends 'base.html' %}{% block title %}(页首标题){% endblock %}{% block pagetitle %}(页面标题){% endblock %}{% block content %}(内容){% endblock %}

{% extends TEMPLATENAME %}标籤的参数TEMPLATENAME可以是一个字面的字串,也可以是一个变量,当使用变量的时候,可以动态地更换继承的模板

15.1.3 利用模板继承更新我们的网站

mysite/templates/base.html

<!DOCTYPE html><html lang="en">    <head>        <meta charset="UTF-8">        <title>{% block title %}{% endblock title %}</title>    </head>    <body>        <h2>{% block content %}{% endblock content %}</h2>        {% if request.user.is_authenticated %}            <p>                {{request.user}} 您已经登入啰~                <a href="/accounts/logout/">登出</a>            </p>            <a href="/restaurants_list/">餐厅列表</a>        {% else %}            <p>您尚未登入喔~<a href="/accounts/login/">登入</a></p>        {% endif %}        <p>若您还没有帐号,请<a href="/accounts/register/">注册</a></p>    </body></html>

mysite/templates/index.html

{% extends 'base.html' %}{% block title %} 首页 {% endblock%}{% block content %}    <p>欢迎来到餐厅王</p>{% endblock %}

15.2 主题2-RequestContext与Context处理器

这边大部分的用法在新版的django中已经不再支援
如果有人知道该如何继续沿用的话麻烦指教一下!
所以只介绍

15.2.3 使用render

from django.shortcuts import render汇入
用法 render(HttpRequest, TEMPLATENAME, DICTIONARY)
第一个参数放request物件
第二个参数放模板
第三个参数放字典
render_to_response来比较
from django.shortcuts import render_to_response汇入
用法 render_to_response(TEMPLATENAME, DICTIONARY)
第一个参数放模板
第二个参数放字典
不能放request参数
所以如果要取得request资讯只能用render

15.3 主题3-自定义过滤器

15.3.1 前置作业

在restaurants目录下建一个资料夹templatetags
在templatetags资料夹中新增一个__init__.py
这样才会被python视为一个套件
接着再新增一个myfilters.py

15.3.2 过滤器函式

之前的menu.html模板
如果想要自定义一个过滤器yes_no

...    <tr>        <td> {{ food.name }} </td>        <td> {{ food.price }} </td>        <td> {{ food.comment }} </td>        <td> {{ food.is_spicy|yes_no:"辣/不辣" }} </td>    </tr>...

这个过滤器接受一个额外的字串参数Y/N,如果is_spicy为真则输出Y,否则输出N
mysite/restaurants/templatetags/myfilters.py

def yes_no(bool_value, show_str):    if bool_value:        return show_str.partition('/')[0]    else:        return show_str.partition('/')[1]

函式的名字不需要跟我们自定义的过滤器名称一样,但是选择相同名称通常是比较好的作法,bool_value是过滤器的第一个参数,他负责接收模板中pipe符号(|)左边的值,而show_str是第二个参数,用来接收过滤器中的额外参数
对照图:

{{ food.is_spicy|yes_no:"辣/不辣" }}   ------------- ------ --------          2.        1.     3.    def yes_no(bool_value, show_str):    ------ ----------  --------       1.       2.        3.

要注意的是,过滤器函式我们总是要保证它是对的,也就是说,我们不允许该函式能够抛出例外
因为任何的例外都会导致网站显示错误,我们应该想办法对于不可避免的例外採行捕捉,并且回传一个空白字串

15.3.3 注册过滤器

写好过滤器函式后接着要注册给Django知道
myfilters.py

from django import templatedef yes_no(bool_value, show_str):    if bool_value:        return show_str.partition('/')[0]    else:        return show_str.partition('/')[1]register = template.Library()register.filter('yes_no', yes_no)

使用register的filter函式来注册,filter函式的第一个参数是过滤器的名称,第二个参数是它对应的过滤器函式
这就是为什么过滤器函式名称不需要跟过滤器的名称一样
要注意的是,不要这样写:

template.Library().filter('yes_no',yes_no)

或是:

reg = template.Library()reg.filter('yes_no',yes_no)

没有把register(名称也要一样)给建立出来就会出现错误
也可以用装饰器来注册

from django import templateregister = template.Library()@register.filter(name='yes_no')def yes_no(bool_value, show_str):    if bool_value:        return show_str.partition('/')[0]    else:        return show_str.partition('/')[1]

该装饰器的参数name是个可选的参数,用来定义过滤器的名称,如果不提供该参数,Django预设会使用过滤器函式的名称作为过滤器名称

15.3.4 载入过滤器

必须在模板里载入它
menu.html

{% load myfilters %}...                <tr>                    <td> {{ food.name }} </td>                    <td> {{ food.price }} </td>                    <td> {{ food.comment }} </td>                    <td> {{ food.is_spicy|yes_no:"辣/不辣" }} </td>                </tr>...

在这里只能载入restaurants app的过滤器
要注意的是前面的步骤必须一模一样

15.4 主题4-使用静态档

网站中会用到的图片、css、js档等被称为静态档(static file)
在上层mysite底下新增两个资料夹static和assets
static资料夹是开发时用来放置静态档的目录
该目录底下可以新增数个子目录来放置不同种类的静态档
比如设置img资料夹来放置图片,或是设置css资料夹来放置css档
而assets是网站真正上线时放置静态档的目录
这两个目录之所以分开,是因为在上线时我们需要将静态档的管理权交给网页伺服器
设定settings.py

...STATIC_URL = '/static/'STATICFILES_DIRS = (    os.path.join(BASE_DIR, 'static'),)STATIC_ROOT = os.path.join(BASE_DIR, 'assets')...

三个参数的说明:

参数说明STATIC_URL静态档的URL pattern,设为/static/代表在网页路径中以/static/开始的便会被视为静态档,如127.0.0.1/static/hello.png、127.0.0.1/static/hi.js,但如果是127.0.0.1/restaurants/static/则会匹配urls.py中的路径而非静态档STATIC_DIRS开发时放置静态档的资料夹,允许底下设置多个资料夹来指示静态档的位置STATIC_ROOT上线时放置静态档的资料夹,在部署时Django藉由python manage.py collectstaticSTATIC_DIRS下发现的静态档複製至STATIC_ROOT。由于当DEBUG设为False后,Django预设便不会处理回传静态档了,藉由指令将这些档案集合到一个资料夹下,方便网页伺服器管理及读取假设网站要放一张图片logo.png在mysite/static/img底下那么在模板上要这样写:
...<img src='/static/img/logo.png'>...

如果有一天STATIC_URL被更改为/static_file/
就得一个一个更改模板中的路径,这样会超累
解决办法是:

{% load staticfiles %}...<img src="{% static 'img/logo.png' %}">...

这里的{% static %}标籤就会自动帮我们找到静态档的路径了
记得要{% load staticfiles %}载入静态档

上一篇:Django学习纪录 14.权限与注册

下一篇:Django学习纪录 16.URL配置与视图进阶技巧


关于作者: 网站小编

码农网专注IT技术教程资源分享平台,学习资源下载网站,58码农网包含计算机技术、网站程序源码下载、编程技术论坛、互联网资源下载等产品服务,提供原创、优质、完整内容的专业码农交流分享平台。

热门文章