自定义模版过滤器

虽然DTL给我们内置了许多好用的过滤器。但是有些时候还是不能满足我们的需求。因此Django给我们提供了一个接口,可以让我们自定义过滤器,实现自己的需求。

模版过滤器必须要放在app中,并且这个app必须要在INSTALLED_APPS中进行安装。然后再在这个app下面创建一个Python包叫做templatetags。再在这个包下面创建一个python文件。比如app的名字叫做book,那么项目结构如下:

- book
    - views.py
    - urls.py
    - models.py
    - templatetags
        - my_filter.py

在创建了存储过滤器的文件后,接下来就是在这个文件中写过滤器了。过滤器实际上就是python中的一个函数,只不过是把这个函数注册到模板库中,以后在模板中就可以使用这个函数了。但是这个函数的参数有限制,第一个参数必须是这个过滤器需要处理的值,第二个参数可有可无,如果有,那么就意味着在模板中可以传递参数。并且过滤器的函数最多只能有两个参数。在写完过滤器后,再使用django.template.Library对象注册进去。示例代码如下:

from django import template

# 创建模板库对象
register = template.Library()

# 过滤器函数
def mycut(value,mystr):
    return value.replace(mystr)

# 将函数注册到模板库中
register.filter("mycut",mycut)

以后想要在模板中使用这个过滤器,就要在模板中load一下这个过滤器所在的模块的名字(也就是这个python文件的名字)。示例代码如下:

{% load my_filter %}

自定义时间计算过滤器:

有时候经常会在朋友圈、微博中可以看到一条信息发表的时间,并不是具体的时间,而是距离现在多久。比如刚刚1分钟前等。这个功能DTL是没有内置这样的过滤器的,因此我们可以自定义一个这样的过滤器。示例代码如下:

# time_filter.py文件

from datetime import datetime
from django import template

register = template.Library()

def time_since(value):
    """
    time距离现在的时间间隔
    1. 如果时间间隔小于1分钟以内,那么就显示“刚刚”
    2. 如果是大于1分钟小于1小时,那么就显示“xx分钟前”
    3. 如果是大于1小时小于24小时,那么就显示“xx小时前”
    4. 如果是大于24小时小于30天以内,那么就显示“xx天前”
    5. 否则就是显示具体的时间 2017/10/20 16:15
    """
    if isinstance(value,datetime):
        now = datetime.now()
        timestamp = (now - value).total_seconds()
        if timestamp < 60:
            return "刚刚"
        elif timestamp >= 60 and timestamp < 60*60:
            minutes = int(timestamp / 60)
            return "%s分钟前" % minutes
        elif timestamp >= 60*60 and timestamp < 60*60*24:
            hours = int(timestamp / (60*60))
            return "%s小时前" % hours
        elif timestamp >= 60*60*24 and timestamp < 60*60*24*30:
            days = int(timestamp / (60*60*24))
            return "%s天前" % days
        else:
            return value.strftime("%Y/%m/%d %H:%M")
    else:
        return value


register.filter("time_since",time_since)

在模版中使用的示例代码如下:

{% load time_filter %}
...
{% value|time_since %}
...

为了更加方便的将函数注册到模版库中当作过滤器。也可以使用装饰器来将一个函数包装成过滤器。示例代码如下:

from django import template
register = template.Library()

@register.filter(name='mycut')
def mycut(value,mystr):
    return value.replace(mystr,"")

模版结构优化

引入模版

有时候一些代码是在许多模版中都用到的。如果我们每次都重复的去拷贝代码那肯定不符合项目的规范。一般我们可以把这些重复性的代码抽取出来,就类似于Python中的函数一样,以后想要使用这些代码的时候,就通过include包含进来。这个标签就是include。示例代码如下:

# header.html
<p>我是header</p>

# footer.html
<p>我是footer</p>

# main.html
{% include 'header.html' %}
<p>我是main内容</p>
{% include 'footer.html' %}

include标签寻找路径的方式。也是跟render渲染模板的函数是一样的。

默认include标签包含模版,会自动的使用主模版中的上下文,也即可以自动的使用主模版中的变量。如果想传入一些其他的参数,那么可以使用with语句。示例代码如下:

# header.html
<p>用户名:{{ username }}</p>

# main.html
{% include "header.html" with username='duodian' %}

模板继承:

在前端页面开发中。有些代码是需要重复使用的。这种情况可以使用include标签来实现。也可以使用另外一个比较强大的方式来实现,那就是模版继承。模版继承类似于Python中的类,在父类中可以先定义好一些变量和方法,然后在子类中实现。模版继承也可以在父模版中先定义好一些子模版需要用到的代码,然后子模版直接继承就可以了。并且因为子模版肯定有自己的不同代码,因此可以在父模版中定义一个block接口,然后子模版再去实现。以下是父模版的代码:

{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
    <link rel="stylesheet" href="{% static 'style.css' %}" />
    <title>{% block title %}我的站点{% endblock %}</title>
</head>

<body>
    <div id="sidebar">
        {% block sidebar %}
        <ul>
            <li><a href="/">首页</a></li>
            <li><a href="/blog/">博客</a></li>
        </ul>
        {% endblock %}
    </div>
    <div id="content">
        {% block content %}{% endblock %}
    </div>
</body>
</html>

这个模版,我们取名叫做base.html,定义好一个简单的html骨架,然后定义好两个block接口,让子模版来根据具体需求来实现。子模板然后通过extends标签来实现,示例代码如下:

{% extends "base.html" %}

{% block title %}博客列表{% endblock %}

{% block content %}
    {% for entry in blog_entries %}
        <h2>{{ entry.title }}</h2>
        <p>{{ entry.body }}</p>
    {% endfor %}
{% endblock %}

需要注意的是:extends标签必须放在模版的第一行。
子模板中的代码必须放在block中,否则将不会被渲染。
如果在某个block中需要使用父模版的内容,那么可以使用{{block.super}}来继承。比如上例,{%block title%},如果想要使用父模版的title,那么可以在子模版的title block中使用{{ block.super }}来实现。

在定义block的时候,除了在block开始的地方定义这个block的名字,还可以在block结束的时候定义名字。比如{% block title %}{% endblock title %}。这在大型模版中显得尤其有用,能让你快速的看到block包含在哪里。

本文作者:博主:
文章标题:Django(九)-自定义过滤器和模板结构
本文地址:https://www.wouldmissyou.com/archives/20/     
版权说明:若无注明,本文皆为“多点部落”原创,转载请保留文章出处。
最后修改:2021 年 01 月 27 日 03 : 17 PM
如果觉得我的文章对你有用,请随意赞赏