Django学习日志五:模板

Django学习日志五:模板1

日志一我们学习了Django的配置,详见:
Django学习日志一Django的配置
日志二我们学习了创建第一个django项目,详见:
Django学习日志二——创建第一个django项目
日志三我们学习了django模型层,详见:
Django学习日志三:模型层
日志四我们学习了django视图层,详见:
Django学习日志四:视图层

下面我们来学习模板的使用:

七、模板

Django遵从MVC模式,其特色化为MVT模式,前文中讲解了M(models)模型和V(views)视图,本章会讲解T所代表的templates模板。

7.1 静态资源配置与加载

绝大多数Django网站都会使用模板语言来渲染HTML页面,并将该页面展示给客户端,其实模板就是经过特殊格式化后输出动态值的HTML文本,它支持简单的逻辑结构,如for循环、if或ifequal条件判断等。

在Django项目中要使用模板,需要通过如下3个不走进行配置。

步骤一:在工程目录hello中创建templates文件夹和static文件夹。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Q2147zWN-1647775787777)(C:\Users\天南之城\AppData\Roaming\Typora\typora-user-images\image-20220317204825363.png)]

步骤二:打开并编辑/hello/hello/setting.py文件,在setting.py文件中找到变量TEMPLATES并配置DIRS参数,配置代码如下:

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

步骤三:打开编辑/hello/hello/setting.py文件,在setting.py文件最后一行添加STATICFILES_DIRS参数,配置代码如下:

STATICFILES_DIRS = [
    os.path.join(BASE_DIR, 'static')
]

上述配置完后,进行stus.html页面的编写,以及路由配置:

示例:查询并展示所有学生信息

​ 在urls.py文件中定义路由

from django.urls import path

from app import views

urlpatterns = [
    path(r'all_student/', views.all_student),
]

​ 在views.py文件中定义视图函数

from django.shortcuts import render

from app.models import Student
def all_student(request):
    if request.method == 'GET':
        stus = Student.objects.all()
        return render(request, 'stus.html', {'stus': stus})

​ 在/hello/templates/目录下新建stus.html文件,页面代码如下


<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>所有学生信息title>
head>
<body>
    {% for stu in stus %}
        <p>
            学生id:{{stu.id}}     学生姓名:{{stu.s_name}}
        p>
    {% endfor %}
body>
html>

分析:

在urls.py文件中定义路由地址,直接访问地址http://127.0.0.1:8080/all_student/会调用all_student()方法,在all_student()方法中使用Student模型进行数据查询,并调用render()方法返回stus.html页面和查询的学生数据。在stus.html页面解析stus参数,渲染出动态的效果。

7.2 模板继承

模板继承和python的类非常相似,可以通过继承的方式获取父模板中的所有元素,模板继承需要事先创建一个基本的“骨架”父模板,该基础模板中包含了网站的所有元素,并定义了可以被子模版覆盖的block。子模板通过继承事先定义的父模板,并拓展父模板文件中定义的block,形成子模版自身的特有内容。

语法如下:

继承模板:

{% extends 'base.html' %}

定义名为title的block:

{% block title %}

{% endblock %}

包含footer.html模板:

{% include 'footer.html' %}

继承父模板block块中的内容:

{{block.super}}

示例:定义父模板base.html


<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>
      {% block title %}
      {% endblock %}
    title>
    {% block extCss %}
        <link href="/static/css/index.css" rel="stylesheet">
    {% endblock %}
head>
<body>
      {% block content %}
      {% endblock %}
body>
html>

父模板一般命名为base.html,它定义了整个网站的“骨架”,而子模版的功能是通过继承父模板并动态地填充父模板中的block,从而形成自己特有的页面内容。

在上述示例中,父模板中定义了3个可以被子模版填充的block,并且在块extCss中引入了static文件夹下的index.css文件。

示例:定义子模版index.html

{% extends 'base.html' %}
{% block title %}
  首页
{% endblock %}
{% block content %}
  <p>子模版填充父模板中的blockp>
{% endblock %}

在子模版中可以使用{% extends %}标签来继承某个父模板,当继承了父模板后,就可以选择性地定义父模板中的block。

如果在子模版中想要覆盖父模板的块extCss,并引入新的CSS文件,但是并不想将父模板的块extCss中的内容覆盖掉,则可以使用{{block.super}}。

示例:修改上述示例中定义的子模版index.html页面,并修改extCss中的内容

{% extends 'base.html' %}

{% block title %}
  首页
{% endblock %}

{% block extCss %}
	{{block.super}}
	<link href="/static/css/main.css" rel="stylesheet">
{% endblock%}

{% block content %}
  <p>子模版填充父模板中的blockp>
{% endblock %}

结论:

  • 子模版可以定义父模板中定义的block,并进行内容的填充。
  • 子模版可以选择性地覆盖父模板的block,如果没有覆盖父模板中的block,则子模版默认填充父模板block中的内容。
  • 子模版可以使用{{block.super}}将父模板中的内容直接继承过来。

7.3 模板中的逻辑表达式

以下是几种常用的逻辑命令:

  • {% for %}:类似Python中的for循环语句,用于循环变量。

    for语法1:

    {% for 变量 in 列表/元组/字典/字符串 %}
    {% endfor %}
    

    for语法2:如果列表/元组/字典/字符串参数为空,则执行empty语句。

    {% for 变量 in 列表/元组/字典/字符串 %}
    {% empty %}
    {% endfor %}
    
  • {% if %}:类似于Python中的if判断语句,用于判断True还是False。

    if语法1:

    {% if 表达式 %}
    {% else %}
    {% endif %}
    

    if语法2:

    {% if 表达式 %}
    {% endif %}
    

    if语法3:

    {% if 表达式 %}
    {% elif 表达式 %}
    {% endif %}
    
  • {{forloop}}:用于循环输出当前循环的次数,一般会嵌套在{% for %}中使用。

    {{forloop}}语法:

    {{forloop.counter}}:表示当前是第几次循环,从1开始
    {{forloop.counter0}}:表示当前是第几次循环,从0开始
    {{forloop.revcounter}}:表示当前是第几次循环,倒数开始,到1停
    {{forloop.revcounter0}}:表示当前是第几次循环,倒数开始,到0停
    {{forloop.first}}:表示是否是第一次循环,如果是第一次循环,则输出为True
    {{forloop.last}}:表示是否是最后一次循环,如果是最后一次循环,则输出为True
    

    示例:在stus.html中解析所有学生信息

    {% extends 'base.html' %}
    
    {% block title %}
      学生信息页面
    {% endblock %}
    
    {% block content %}
    
        {% for stu in stus %}
            ID:{{stu.id}}
            {% if forloop.counter == 1 %}
                <span style="color:red;">
                    学生:{{stu.s_name}}
                span>
            {% else %}
                <span style="color:yellow;">
                    姓名:{{stu.s_name}}
                span>
            {% endif %}
    
            {% if stu.s_sex %}
                性别:男
            {% else %}
                性别:女
            {% endif %}
            <br/>
        {% endfor %}
    
    {% endblock %}
    

    该stus.html页面使用了模板继承,继承于base.html,并自定义了block需要动态展示的内容。该模板中使用了变量、模板标签、过滤器。具体分析如下:

    • 用两个大括号括起来的参数,称为变量。
    • 被大括号和百分号括起来的参数,称为模板标签。在示例代码中包含了if标签、ifequal标签、forloop标签。

7.4 注解

当模板中某行代码或某几行代码需要被屏蔽不执行的时候,应在模板中对代码进行注解,注解方式有以下3种:

  • HTML注解:
  • 模板中单行注解:{# 注解内容 #}
  • 模板中多行注解:{% comment %}多行注解内容{% endcomment %}

示例:HTML注解、单行注解、多行注解的使用:

{% extends 'base.html' %}

{% block title %}
  学生信息页面
{% endblock %}

{% block content %}


{# 我是隐藏部分,在页面中不允许而且不展示出来 #}

{% comment %}
	我是隐藏部分,我不会在页面中展示出来,也不会运行
{% endcomment %}

{% endblock %}

<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>
		学生信息页面
    title>
        <link href="/static/css/index.css" rel="stylesheet">
head>
<body>
	
body>
html>

注意:在进行注解的时候,不能注解模板标签,否者会报模板标签相关的错误提示。而{# 注解内容 #}和{% comment %}注解内容{% endcomment %}可以注解模板标签。

7.5 过滤器

在模板中虽然可以通过变量的输出来实现动态网页的效果,但是这样的 操作不灵活,可以使用过滤器来控制变量显示的格式,使用管道符号“|”来凝结变量和过滤器符号。

语法如下:

变量|过滤器

Django提供了各种各样有用的过滤器来封装Web开发中常见的文本处理工作。例如,字符串的大小写变换、字符串首字母大写、格式化日期、列表截取、字符串长度等。

示例:常见过滤器的使用


{{'python'|upper}}


{{'PYTHON'|lower}}


{{3|add:'4'}}


{{'python'|capfirst}}


{{'study python is very happy'|cut:' '}}


{{''|default:'nothing'}}


{{'python'|first}}


{{'python'|last}}


{{'python'|length}}


{{'python'|random}}

django的内建过滤器介绍如下:

过滤器 描述 使用形式
add 将value的值增加2。 {{value|add:‘2’}}
addslashes 在value中的引号前增加反斜线。 {{value|addslashes}}
capfirst 将value的第一个字符转换成大写形式。 {{value|capfirst}}
cut 从给定的value中删除所有arg的值。 {{value|cut:arg}}
date 格式化时间格式。 {{value|date:“Y-m-d H:M:S”}}
default 如果value是False,那么输出使用缺省值。 {{value|default:“nothing”}}
default_if_none 如果value是None,那么输出使用缺省值。 {{value|default_if_none:“nothing”}}
dictsort 如果value是一个字典,那么返回值是按照关键字排序的结果。例如:value是[{‘name’:‘python’},{‘name’:‘java’},{‘name’:‘c++’}],那么输出是[{‘name’:‘c++’},{‘name’:‘java’},{‘name’:‘python’}] {{value|dictsort:“name”}}
dictsortreversed 如果value的值是一个字典,那么返回值是按照关键字排序的结果的反序。 {{value|dictsortreversed:“name”}}
divisibleby 如果value能够被arg整除,那么返回值将是True。例如,value是9,arg是3,那么输出将是True。 {{value|divisibleby:arg}}
escape 替换value中的某些字符,以适应HTML格式。 {{value|escape}}
filesizeformat 格式化value,使其成为易读的文件大小。例如,13KB、4.1MB。 {{value|filesizeformat}}
first 返回列表/字符串中的第一个元素 {{value|first}}
iriencode 如果value中有非ASCII字符,那么将其转化成适合URL的编码,如果value已经进行过URL编码,那该操作不会再起作用。 {{value|iriencode}}
join 使用指定的字符串来连接一个list,作用如同Python中的str.join(list)。例如,value是[‘a’,‘b’,‘c’],arg是"//",那么输出将是a//b//c。 {{value|join:“arg”}}
last 返回列表/字符串中的最后一元素。 {{value|last}}
length 返回value的长度。 {{value|length}}
length_is 如果value的长度等于arg,那么将返回True。例如,value是[‘a’,‘b’,‘c’],arg是3,那么返回True。 {{value|length_is:“arg”}}
linebreaks value中的"\n"将被
替代,并且整个value使用

包围起来。
{{value|linebreaks}}
linebreaksbr value中的"\n"将被
替代。
{{value|linebreaksbr}}
linenumbers 显示的文本,带有行数。 {{value|linenumbers}}
ljust 在一个给定宽度的字段中,左对齐显示value。 {{value|ljust}}
center 在一个给定宽度的字段中,中心对齐显示value。 {{value|center}}
rjust 在一个给定宽度的字段中,右对齐显示value。 {{value|rjust}}
lower 将一个字符串转换成小写形式。 {{value|lower}}
random 从给定的list中返回一个任意的Item。 {{value|random}}
removetags 删除value中tag1,tag2…的标签。 {{value|removetags:“tag1 tag2 tag3…”}}
safe 当系统设置autoescaping打开的时候,该过滤器使输出不进行escape转换。 {{value|safe}}
safeseq 与safe基本相同,但safe是针对字符串,而safeseq是针对多个字符串组成的safeseq。 {{value|safeseq}}
slice 与Python语法中的slice相同。 {{some_list|slice:“2”}}
striptags 删除value中的所有HTML标签。 {{value|striptags}}
time 格式化时间输出。 {{value|time:“H:i”}}或{{value|time}}
title 将一个字符串转换成title格式。 {{value|title}}
truncatewords 将value切成truncatewords指定的单词数目。例如,value是Joel is a slug,那么输出就是Joel is。 {{value|truncatewords:2}}
upper 将一个字符串转换成大写形式。 {{value|upper}}
urlencode 将一个字符串进行URL编码。 {{value|urlencode}}
wordcount 返回字符串中单词的数目。 {{value|wordcount}}

7.6 反向解析

在6.4重定向redirect小节中,为了避免在视图函数中出现硬编码URL,需要使用命名空间namespace和视图函数对应的URL模式中的name参数。在Django的模板中定义URL反向解析功能与在重定向中定义URL反向解析有不同的调用方式,在重定向中定义URL反向解析使用{% url %}语法,其中参数是可选项。

语法如下:

{% url 'namespace:name' 参数1 参数2 参数3 ... %}

示例:模板中定义URL反向解析

​ 在hello/urls.py中定义总路由

from django.urls import path, include

from app import views

urlpatterns = [
    path('app/', include(('app.urls', 'app'), namespace='app/')),
]

​ 在hello/app/urls.py中定义路由

from django.urls import path

from app import views

urlpatterns = [
    path(r'student//', views.sel_one_student, name='stu'),
    path(r'login/', views.login, name='login'),
]

​ 在stus.html页面中定义URL反向解析地址

{% extends 'base.html' %}

{% block title %}
  学生信息页面
{% endblock %}

{% block content %}

    <a href="{% url 'app:stu' 1 %}">
        查看学生详情地址
    a>
	<br>
    <a href="{% url 'app:login' %}">
        Session案例中定义的URL
    a>

{% endblock %}

在浏览器中输入http://127.0.0.1:8080/all_student/:

  • 点击“查看学生详情地址”,模板解析{% url’app:stu’ 1 %}结果为/app/student/1/。如果请求的URL路径中带有参数,则在URL反向解析的时候可以直接在{% url namespace:name 参数 %}中添加参数。
  • {% url ‘app:login’ %},模板解析后的结果为/app/login/

  1. 本日志所有内容学习自《Python Web开发从入门到精通》(王海飞编著)、网络资源以及本人的调试 ↩︎

你可能感兴趣的:(python,后端,django入门,python,django,后端)