我爱Django框架之Django模板过滤器,结构优化与静态资源文件(你想要的这都有!!!)

Django模板常用的过滤器

       •在模板中,很多时候需要对传递过来的数据进行处理之后才能使用,在Python中一般是通过函数来完成对数据的处理,在Django框架的模板中,则是通过过滤器来实现对数据的处理
       •过滤器是通过|来使用的,用法为 视图函数变量 | 模板过滤器:“参数”,其中参数为可选项

add过滤器

       •将传递进来的参数添加到原来的参数上面,add过滤器会尝试将值和参数转换成整形然后进行简单相加,得到最好的值
       •如果类型转换失败,则会将数值和参数进行拼接
       •如果是参数是字符串,那么会拼接成字符串
       •如果是参数列表,那么会拼接成一个列表

代码测试如下:
       •首先创建项目django_filter,再创建名为front的app,然后在项目目录下的settings.py (django_filter/settings.py) 进行模板(templates)的路径配置:

import os
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',
            ],
        },
    },
]

       •项目目录下的urls.py文件:

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('front.urls')),
]

       •front app下视图views.py文件如下:

from django.shortcuts import render


def index(request):  #定义视图函数
    context = {
        'number': 8,
        'char': '88',
        'li1': [8, 9],
        'li2': [6, 2],
    }
    return render(request, 'index.html', context=context)

       •在项目目录下新建templates目录,又在templates目录下新建index.html模板文件如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
        <p>首页</p>
    <p>原始数字:{{ number }}</p>
    <p>数字加2:{{ number | add:'2' }}</p>
    <p>数字加a:{{ number | add:'a' }}</p>
    <p>字母加a:{{ char | add:'a' }}</p>
    <p>列表相加:{{ li1 | add:li2 }}</p>
</body>
</html>

       •front app下新建urls,py文件进行视图函数路由的配置 如下:

from django.urls import path

from . import views

urlpatterns = [
    path('add/', views.index)
]

网页显示如下;
在这里插入图片描述
       •由上面可以看出,当不同类型的变量进行匹配相加,如果两个变量相加没有任何意义,就会返回空字符串,不会报错

cut过滤器

       •用于移除变量值中所有指定的字符串,类似于Python语法中的的replace()方法

代码测试如下:
       •模板index.html文件如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <p>前台首页</p>
    <p>{{ 'Hello World' | cut:'o' }}</p>
</body>
</html>

网页显示如下:
在这里插入图片描述

date过滤器

       •用于将一个日期转换成特定格式的字符串

具体的字符含义如下表所示:

格式字符含义范围和举例
Y四位数字的年份2020
m两位数字的月份01–12
n月份,1-9前面没有0前缀1–12
d两位数字的日01–31
j日,1-9前面没有0前缀1–31
h小时,12小时格式的,1-9前面有0前缀01–12
g小时,12小时格式的,1-9前面没有0前缀1–12
H小时,24小时格式的,1-9前面有0前缀01–23
G小时,24小时格式的,1-9前面没有0前缀1–23
i分钟,1-9前面有0前缀00–59
s秒,1-9前面有0前缀00-59

代码测试如下:
       •模板index.html文件如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <p>前台首页</p>
    <p>原始时间格式:{{ now }}</p>
    <p>自定义时间格式1:{{ now | date:'Y/m/d H:i:s' }}</p>
    <p>自定义时间格式2:{{ now | date:'Y/n/j g:i:s' }}</p>
</body>
</html>

       •front app下视图views.py文件如下:

from datetime import datetime

from django.shortcuts import render


def index(request):
    context = {
        'number': 8,
        'char': '88',
        'li1': [8, 9],
        'li2': [6, 2],
        'now': datetime.now()
    }
    return render(request, 'index.html', context=context)

网页显示如下:
在这里插入图片描述

default过滤器

       •如果传递到模板中的变量被判断为False,比如空字符串" "、空列表[]、空字典{}、空值None等在条件判断中为False的值,可以使用default过滤器提供的默认值代替原来的空值

代码测试如下:
       •模板index.html文件如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <p>前台首页</p>
    <p>原始时间格式:{{ now }}</p>
    <p>信息info:{{ info|default:'信息正在完善中请稍等!!'}}</p>
    <p>自定义时间格式:{{ now | date:'Y/m/d H:i:s'|default:'暂未设置时间' }}</p>

</body>
</html>

       •front app下视图views.py文件如下:

from datetime import datetime

from django.shortcuts import render


def index(request):
    context = {
        'number': 8,
        'char': '88',
        'li1': [8, 9],
        'li2': [6, 2],
        'info': '',
        'now': None,
    }
    return render(request, 'index.html', context=context)

网页显示如下:
在这里插入图片描述
可以看出:
       •在传递的变量被判定为空值(Flase)时,就会显示指定的默认值
       •同时,在有意义的前提下,多个过滤器可以自由结合使用

first和last过滤器

       •first过滤器返回列表、元组、字符串中的第一个元素,last过滤器返回列表、元组、字符串中的最后一个元素

代码测试如下:
       •模板index.html文件如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <p>图书首页</p>
    <p>第一本书:{{ books|first }}</p>
    <p>最后一本书:{{ books|last }}</p>
</body>
</html>

       •front app下视图views.py文件如下:

from django.shortcuts import render


def index(request):
    context = {
        'books': ['Python头秃日记', 'Java冲冲冲', 'PHP天下第一'],
    }
    return render(request, 'index.html', context=context)

网页显示如下:
在这里插入图片描述

floatformat过滤器

       •使用四舍五入的方式格式化一个浮点类型变量,floatformat过滤器没有传递任何参数时,会默认在小数点后保留一个小数,没有传递任何参数并且小数后面全是0时,只会保留整数,传递一个参数时,会保留指定的小数位数
代码测试如下:
       •模板index.html文件如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<p>前台首页</p>
<ul>
    <li>{{ 3.14|floatformat }}</li>
    <li>{{ 3.1415|floatformat }}</li>
    <li>{{ 3.1415926|floatformat:4 }}</li>
    <li>{{ 3.00000|floatformat }}</li>
    <li>{{ 3.00000000|floatformat:4 }}</li>
</ul>
</body>
</html>

网页显示如下:
在这里插入图片描述

join过滤器

       •类似于Python中的join()方法,将列表、元组、字符串中的元素用指定的字符进行拼接
代码测试如下:
       •模板index.html文件如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <p>首页</p>
    <p>当前日期:{{ date | join:'--' }}</p>
</body>
</html>

       •front app下视图views.py文件如下:

from django.shortcuts import render


def index(request):
    context = {
        'date': ['2021', '03', '22'],
    }
    return render(request, 'index.html', context=context)

网页显示如下:
在这里插入图片描述

safe过滤器

之前已经用到过,它是用来标记一个字符串是安全的,会关掉这个字符串的自动转义,如果变量是一个不包含任何特殊字符的普通字符串,会把字符串正常输入,如果value是html类型代码,会将html代码渲染到浏览器中
代码测试如下:
       •模板index.html文件如下:

<!DOCTYPE html>
<html lang="en">
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <p>前台首页</p>
    <p>日期:{{ date | join:'--' }}</p>
    <p>普通字符串:{{ info }}</p>
    <p>安全字符串:{{ info | safe }}</p>
</body>
</html>

       •front app下视图views.py文件如下:

from django.shortcuts import render


def index(request):
    context = {
        'date': ['2021', '03', '22'],
        'info': '<a href="https://blog.csdn.net/qq_45261963?spm=1010.2135.3001.5343">个人博客首页</a>'
    }
    return render(request, 'index.html', context=context)

网页显示如下:
在这里插入图片描述

slice过滤器

slice过滤器,类似于Python中的切片操作,对列表、字符串等进行切片,需要传递整型参数
假如为下标名为index,则不同的方式意义上有所不同,index范围是从1开始到被切片对象的长度
index和 : index的含义一致,均为从1到index对应的元素(包括该元素)
index:为index对应的元素之后的元素(不包括该元素)
代码测试如下:
       •模板index.html文件如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <p>前台首页</p>
    <p>日期:{{ date | slice:'1' }}</p>
    <p>日期:{{ date | slice:':1' }}</p>
    <p>日期:{{ date | slice:'1:' }}</p>
    <p>日期:{{ date | slice:'2' }}</p>
    <p>日期:{{ date | slice:':2' }}</p>
    <p>日期:{{ date | slice:'2:' }}</p>
    <p>字符串:{{ info | slice:'3' }}</p>
    <p>字符串:{{ info | slice:':3' }}</p>
    <p>字符串:{{ info | slice:'6:' }}</p>
    <p>字符串:{{ info | slice:'6' }}</p>
    <p>字符串:{{ info | slice:':9' }}</p>
    <p>字符串:{{ info | slice:'9:' }}</p>
</body>
</html>

       •front app下视图views.py文件如下:

from django.shortcuts import render


def index(request):
    context = {
        'date': ['2020', '09', '05'],
        'info': 'hello world'
    }
    return render(request, 'index.html', context=context)

网页显示如下:
在这里插入图片描述

striptags标签

用于删除字符串中所有的html标签
代码测试如下:
       •模板index.html文件如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <p>首页</p>
    <p>个人信息:{{ info | striptags }}</p>
</body>
</html>

       •front app下视图views.py文件如下:

from django.shortcuts import render


def index(request):
    context = {
        'date': ['2021', '03', '22'],
        'info': '<a href="https://blog.csdn.net/qq_45261963?spm=1010.2135.3001.5343">个人博客首页</a>'
    }
    return render(request, 'index.html', context=context)

网页显示如下:在这里插入图片描述

truncatechars过滤器

如果给定的字符串长度超过了truncatechars过滤器指定的长度,就会对字符串进行切割,并且会拼接三个点来作为省略号 表示后面内容被省略了
如果没有超过truncatechars过滤器指定的长度,则不做任何处理
这在网站标题显示中应用很广泛
代码测试如下:
       •模板index.html文件如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <p>前台首页</p>
    <p>信息1:{{ info | truncatechars:'10' }}</p>
    <p>信息2:{{ info | truncatechars:'50' }}</p>
</body>
</html>

       •front app下视图views.py文件如下:

from django.shortcuts import render


def index(request):
    context = {
        'date': ['2021', '03', '22'],
        'info': 'Python由荷兰数学和计算机科学研究学会的Guido van Rossum 于1990 年代初设计'
    }
    return render(request, 'index.html', context=context)

网页显示如下:
在这里插入图片描述

其他常见过滤器

其他常用过滤器如下表:

过滤器作用举例
length获取一个列表、元组、字符串、字典的长度{ value|length }}
lower将变量中所有的字符全部转换成小写{{ value|lower }}
upper将指定的字符串全部转换成大写{{ value|upper }}
random在给定的列表、字符串、元组中随机选择一个值{{ value|random }}

       •更多过滤器可以查看Django中文文档https://docs.djangoproject.com/zh-hans/2.0/或者查看Django源码django.template.defaultfilters

模板结构优化

在实际项目中,网页界面都具有一定的结构,包括头部、主体内容、底部内容等部分,如Python菜鸟教程一样:

每个网页都有一样的头部信息,和底部信息

在这里插入图片描述
现在模拟如上情况,代码测试如下:
       •模板index.html文件如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <ul>
        <li>发现</li>
        <li>关注</li>
        <li>消息</li>
    </ul>
    <h1>前台首页</h1>
    <p>信息:{{ info }}</p>
</body>
</html>

       •模板目录下新建info.html文件如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <ul>
        <li>发现</li>
        <li>关注</li>
        <li>消息</li>
    </ul>
    <h1>个人中心</h1>
</body>
</html>

       •front app下视图views.py文件如下:

from django.shortcuts import render


def index(request):
    context = {
        'date': ['2021', '03', '22'],
        'info': 'Python由荷兰数学和计算机科学研究学会的Guido van Rossum 于1990 年代初设计'
    }
    return render(request, 'index.html', context=context)


def info(request):
    return render(request, 'info.html')

       •front app下视图urls.py文件如下:

from django.urls import path

from . import views

urlpatterns = [
    path('', views.index, name='index'),
    path('info/', views.info, name='info'),
]

网页显示如下:
在这里插入图片描述

可以看到,前台首页和个人中心页都有发现、关注、消息等栏目,但是存在一些问题:
       •页面较多时HTML代码重复多、复用性较低
       •在需要修改时,需要对每个HTML文件进行修改可维护性较差

上述情况,有两种方法解决:
       •引入模板
       •模板继承

引入模板

有时候一些HTML代码在许多模板文件中都会用到,如果使用大量重复代码不符合项目的规范,一般可以把重复性的代码抽取出来,就类似于Python中的函数一样,以后想要使用这些代码的时候,就通过include标签包含进来即可使用

       •模板目录下新建header.html文件保存公共的头部代码:

<ul>
    <li>发现</li>
    <li>关注</li>
    <li>消息</li>
</ul>

       •模板index.html文件如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    {% include 'header.html' %}
    <h1>前台首页</h1>
    <p>信息:{{ info }}</p>
</body>
</html>

       •模板info.html文件如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    {% include 'header.html' %}
    <h1>个人中心</h1>
</body>
</html>

       •效果与之前代码一样

include标签寻找路径的顺序和render渲染模板是一样的
默认include标签引用模板时会自动使用主模板中的上下文,也即可以自动使用主模板中的变量

       •front app下视图views.py文件如下:

from django.shortcuts import render


def index(request):
    context = {
        'date': ['2021', '03', '22'],
        'info': 'Python由荷兰数学和计算机科学研究学会的Guido van Rossum 于1990 年代初设计'
    }
    return render(request, 'index.html', context=context)


def info(request):
    context = {
        'username': 'Ycx'
    }
    return render(request, 'info.html', context=context)

       •模板header.html文件如下:

<ul>
    <li>发现</li>
    <li>关注</li>
    <li>消息</li>
    <li>{{ username }}</li>
</ul>

网页显示如下:
在这里插入图片描述

由上可得,如果在视图函数中传递了变量,模板中也会进行渲染

模板继承

在模板的结构优化方面,模板继承比引入模板的灵活性更高、应用更广泛

Python中的类:
在父类中可以先定义好一些变量和方法,然后在子类中可以调用并使用父类方法

模板继承类似于Python,也可以在父模板中先定义好一些子模板需要用到的代码,然后子模板直接继承,同时因为子模板有需要自己实现的代码,因此需要在父模板中定义一个block接口,用于子模板的扩展

       •front app下视图views.py文件如下:

from django.shortcuts import render


def index(request):
    context = {
        'date': ['2021', '03', '22'],
        'info': 'Python由荷兰数学和计算机科学研究学会的Guido van Rossum 于1990 年代初设计'
    }
    return render(request, 'index.html', context=context)


def info(request):
    context = {
        'username': 'Ycx'
    }
    return render(request, 'info.html', context=context)


def book(request):
    return render(request, 'book.html')

       •front app下视图urls.py文件如下:

from django.urls import path

from . import views

urlpatterns = [
    path('', views.index, name='index'),
    path('info/', views.info, name='info'),
    path('book/', views.book, name='book'),
]

       •模板目录下新建base.html文件如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>{% block title %}前台{% endblock %}</title>
</head>
<body>
    <ul>
        <li>发现</li>
        <li>关注</li>
        <li>消息</li>
        <li>{{ username }}</li>
    </ul>
    {% block content %}
        <h1>父模板</h1>
    {% endblock %}
    <footer>
        网站底部
    </footer>
</body>
</html>

上述base.html定义好一个基础的html框架,然后定义好需要的block接口,让子模板根据具体需求来实现,并通过extends标签来引用父类中的方法

       •模板目录下新建book.html文件如下:

{% extends 'base.html' %}

{% block title %}
    图书
{% endblock %}

<h1>block外:图书首页</h1>

{% block content %}
    <h1>block内:图书首页</h1>
{% endblock %}

网页显示:
在这里插入图片描述

由上可以看出:
子模板中的代码必须放在block中,否则不会被渲染
如果在父模板的block中定义了内容、而子模板不重写,则直接使用父模板中的内容,如果子模板进行重写,则渲染重写后的内容

如果需要在某个block中使用父模板的内容,可以使用{{ block.super }}来实现继承
       •模板目录下book.html文件如下:

{% extends 'base.html' %}

{% block title %}
    图书
{% endblock %}

<h1>block外:图书首页</h1>

{% block content %}
    <h1>block内:图书首页</h1>
    {{ block.super }}
{% endblock %}

网页显示:
在这里插入图片描述

注意

extends标签必须放在整个模板文件的最前面
在定义block时,除了在block开始的地方定义block的名字,还可以在block结束的地方定义,如{% block title %}{% endblock title %}。在大型模板中使用显得尤其有用,可以清晰看到block所包含的范围

加载静态资源文件

网页中,一般不仅只有一个html框架,还需要css样式文件、js执行文件和图片等,因此需要实现在DTL中加载静态文件

在DTL中,使用static标签来加载静态文件。要使用static标签,首先需要{% load static %}

具体步骤如下:
       •(1)在项目目录下的settings.py文件中,注册需要加载静态资源的app 确保django.contrib.staticfiles已经添加到settings.INSTALLED_APPS
              项目目录下的settings.py文件如下:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'front',
]

       •(2)确保在settings.py中设置了STATIC_URL
              STATIC_URL是Django默认实现,如下:

STATIC_URL = '/static/'

       •(3)在已经注册了的app下创建static目录,然后再在static文件夹下创建一个名为当前app名的目录,再把静态文件放到这个目录下

这里就是在front目录下创建static目录,用于保存只会在front app中用到的静态资源文件
       •模板目录下info.html文件如下:

{% load static %}

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    {% include 'header.html' with username='Jackson' %}
    <h1>个人中心</h1>
    <img src="{% static 'monkey.png' %}" alt="猴子">
</body>
</html>

网页显示:
在这里插入图片描述
在app下的static目录下再创建名为app名的目录,是因为只在app下创建static目录并将静态资源文件保存到其中,会出现问题:
       •如果直接把静态文件放在static文件夹下,那么在模板加载静态文件时按照INSTALLED_APPS中注册app的顺序依次查找对应的资源文件,如果在多个app之间有同名的静态文件,就可能会产生混淆而加载错误
       •而在static文件夹下加了一个同名app文件夹,在模板中加载的时候就是使用app/monkey.png,这样就可以避免产生混淆

可以看到,总体上,静态资源文件加载有两种方式:
       •app内部资源文件加载:
              •在每个app内部建立static目录,并再创建名为app名的子目录,同时在settings.py中配置STATIC_URL,查找资源文件时会根据安装的app的顺序进行查找

       •项目资源文件加载:
              •在项目目录下创建static目录用于保存公共资源文件,并在settings.py中配置STATICFILES_DIRS。也可以在static目录下创建对应于每个app的子目录,用于保存每个app的资源文件

建议使用第二种方式,项目结构更加合理,也更方便管理静态资源文件

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值