lxinghua

博客园 首页 新随笔 联系 订阅 管理

准备工作

1. 关于自定义

官方文档:https://docs.djangoproject.com/zh-hans/3.2/howto/custom-template-tags/

2. 路径配置

公用

1. 创建一个新的app,然后将自定义的模板标签和过滤器的python文件放置在新的app下;

2. app注册

某个app特有

1. app目录下创建一个名为templatetags的文件夹(文件夹与包的差异在于文件夹内是否有__init__.py文件,若有则是包,无则为文件夹),所有templatetags文件夹中需要添加__init__.py文件,将其变成一个包。

2. 并在templatetage包中建立自定义过滤器customter_filters.py文件和自定义标签customter_tags.py文件

自定义模板过滤器

1. 定义

1. {{ 模板变量|过滤器[:字符串] }}

2. 过滤器是一个python函数,它有一个或者两个参数

3. 第一个参数 是传进来的模板变量

4. 第二个参数 可有可能没有  指向字符串参数

5. 自定义

customter_filter.py自定义过滤器

from django import template                            
                                                       
register = template.Library()   # 变量名必须叫register       
                                                       
@register.filter('to_male') #--1                      
#@register.filter() #--2                                
def to_sex(value, arg='zh'):  #默认中文,在调用是可用不用提供         
    change = {                                         
        'zh': ('', ''),                              
        'en': ('Female', 'male')                       
    }                                                  
    return change[arg][int(value)]                     
                                                       
# register.filter('to_male', to_sex) #--1    # 自定义过滤器注册
# register.filter(to_sex) #--2   #函数名和过滤器名相同时,可不同提供过滤器名

2. 注册

from django import template                         
                                                    
register = template.Library()   # 变量名必须叫register    
                                                                                                               
register.filter('to_male', to_sex)    # 自定义过滤器注册    

a. 可按以上三步进行自定义过滤器注册

b. 在函数名与过滤器名不一致时,可采用#--1模式注册,需要提供过滤器名称,@采用的是装饰器模式直接注册

c. 在函数名与过滤器名一致时,可采用#--2模式注册,不用提供过滤器名称,直接采用函数名为过滤器名,同样可以直接采用装饰器进行注册。

3. 使用

首先需要导入自定义过滤器文件 {% load customer_filters %}  

其次就是过滤器调用  <td>{{ student.sex|to_male:'zh' }}</td> 

{% extends 'teacher/base.html' %}  <!--当前模板继承父模板base.html-->
{% load static %}  <!--#此处导入static后,将不再调用setting文件中的STATIC_URL = '/static/',直接调用STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')] -->
{% load customer_filters %}    #调用前需要导入自定义过滤器文件
{% block title %}
    <title>首页面</title>
{% endblock %}
{% block link %}
    <link rel="stylesheet" href="{% static 'teacher/index.css' %}">
{% endblock %}
{% block content %}
    <table>
        <tr>
            <th>序号</th>
            <th>姓名</th>
            <th>年龄</th>
            <th>性别</th>
        </tr>
        {% for student in students %}
        <tr {% if student.sex == '0' %}style="color:red;"{% endif %}>
            <td><a href="{% url 'teacher:detail' student.name %}">{{ forloop.counter }}</a></td>  <!-- forloop.counter0从0开始计数,没有0则从1开始计数-->
            <td>{{ student.name }}</td>
            <td>{{ student.age }}</td>
            <td>{{ student.sex|to_male:'zh' }}</td>   #调用方式,再默认'zh'时,可不用输入“:'zh'”
        </tr>
        {% endfor %}
    </table>
    模板过滤器:{{ lt.0|add:5 }}
{% endblock %}

自定义模板标签

模板标签可以做任何事

{% %}

1. 简单标签  django.template.Library.simple_tag()

1. 定义

from datetime import datetime
from django import template

register = template.Library()

#方式1:
#@register.simple_tag(name='current')
#def current_time():
#    return datetime.now().strftime('%Y年%m月%d日 %H:%M:%S')

#方式2:
#@register.simple_tag(name='current')
#def current_time(format_str):
#    return datetime.now().strftime(format_str)

#方式3:
@register.simple_tag(name='current', takes_context=True)
def current_time(context):
    format_str = context['format_str']
    return datetime.now().strftime(format_str)

2.注册

from django import template

register = template.Library()

@register.simple_tag(name='current')

上述三行代码表示标签的注册(方法同过滤器注册方式)

3.使用

{% extends 'teacher/base.html' %}  <!--当前模板继承父模板base.html-->
{% load static %}  <!--#此处导入static后,将不再调用setting文件中的STATIC_URL = '/static/',直接调用STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')] -->
{% load customer_filters %}
{% load customer_tags %}     #同样的,调用前需要导入自定义customer_tage文件
{% block title %}
    <title>首页面</title>
{% endblock %}
{% block link %}
    <link rel="stylesheet" href="{% static 'teacher/index.css' %}">
{% endblock %}
{% block content %}
    <table>
        <tr>
            <th>序号</th>
            <th>姓名</th>
            <th>年龄</th>
            <th>性别</th>
        </tr>
        {% for student in students %}
        <tr {% if student.sex == '0' %}style="color:red;"{% endif %}>
            <td><a href="{% url 'teacher:detail' student.name %}">{{ forloop.counter }}</a></td>  <!-- forloop.counter0从0开始计数,没有0则从1开始计数-->
            <td>{{ student.name }}</td>
            <td>{{ student.age }}</td>
            <td>{{ student.sex|to_male:'zh' }}</td>
        </tr>
        {% endfor %}
    </table>
    模板过滤器:{{ lt.0|add:5 }}
    模板过滤器:{{ lt|first }}
    <h3>当前时间:{{ now }}</h3>
    <h3>当前时间+过滤器:{{ now|date:'Y年m月d日 H:i:s' }}</h3>
    {# #方式1:<h3>当前时间+自定义模板标签:{% current '%Y年%m月%d日 %H:%M:%S' %}</h3> #}
    {# #方式2:<h3>当前时间+自定义模板标签:{% current format_str %}</h3> #}
    {# #方式3: #}
    <h3>当前时间+自定义模板标签:{% current %}</h3>      #方式1/2/3对应三种标签注册方法
    <h3>{{ format_str }}</h3>
{% endblock %}

方式3需要在views.py文件中对context输出项目进行定义

from django.shortcuts import render, redirect, reverse
from django.http import HttpResponse
from datetime import datetime

def index(request):
    now = datetime.now()
    #now = now.strftime('%Y年%m月%d日 %H:%M:%S')  #对时间呈现方式进行格式化
    format_str = '%Y年%m月%d日 %H:%M:%S'
    lt = [1, 2, 3]
    dt = {'name': 'tiger', 'age': 18}
    js = '<script>alert("1")</script>'
    html = '<h1>我是安全的</h1>'
    students =[
        {'name':'tager', 'age':18, 'sex':'1', 'course':['python', 'music', 'java', '前端']},
        {'name': 'liuda', 'age': 19, 'sex': '0', 'course':['python', 'music', 'java', '前端']},
        {'name': 'lier', 'age': 20, 'sex': '1', 'course':['python', 'music', 'java', '前端']},
        {'name': 'zhangsan', 'age': 18, 'sex': '0', 'course':['python', 'music', 'java', '前端']},
        {'name': 'wangwu', 'age': 21, 'sex': '1', 'course':['python', 'music', 'java', '前端']},
    ]
    for i in students:
        value = i['course']
    def func():
        return '函数'

    return render(request, 'teacher/index.html', context={
        'now': now,
        'lt': lt,
        'dt': dt,
        'func': func,
        'js': js,
        'html': html,
        'students': students,
        'format_str': format_str,
        'value': value
    })

4. 引用上下文变量

  a. format_str:在views.py定义---->通过context传递到模板文件---->通过自定义模板标签传递到自定义模板标签函数

  b. takes_context=True 实现从views.py中context中获取需要的变量,第一个参数必须是context,且takes_context必须为True

#方式3:
@register.simple_tag(name='current', takes_context=True)
def current_time(context):
    format_str = context['format_str']
    return datetime.now().strftime(format_str)

 

2. 包含标签  django.template.Library.inclusion_tag()

1. 定义

from datetime import datetime
from django import template

register = template.Library()

#方式1:
#@register.inclusion_tag('teacher/show_list.html')
#def show_list(value):   #定义一个函数,接收模板变量
#    return {'ls': value}

#方式2:
@register.inclusion_tag('teacher/show_list.html')
def show_list(value, style='link'):   #定义一个函数,接收模板变量,style默认link,html文件调用时,若为link,可不同提供
    return {'ls': value, 'style': style}

#方式3:
#@register.inclusion_tag('teacher/show_list.html', takes_context=True)
#def show_list(context, style='link'):   #定义一个函数,接收模板变量,style默认link,html文件调用时,若为link,可不同提供
#    value = context['value']
#    return {'ls': value, 'style': style}

2.注册

from django import template

register = template.Library()

@register.inclusion_tag('teacher/show_list.html')

上述三行代码表示标签的注册(方法同过滤器注册方式)

3.使用

show_list.html代码

{% if style == 'button' %}
<div>
    {% for l in ls %}
    <button>{{ l }}</button>
    {% endfor %}
</div>

{% elif style == 'link' %}
<div>
    {% for l in ls %}
    <a>{{ l }}</a>
    {% endfor %}
</div>

{% else %}
<!--方式1:-->
<ul>
    {% for l in ls %}
    <li>{{ l }}</li>
    {% endfor %}
</ul>

{% endif %}

index.html代码

tends 'teacher/base.html' %}  <!--当前模板继承父模板base.html-->
{% load static %}  <!--#此处导入static后,将不再调用setting文件中的STATIC_URL = '/static/',直接调用STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')] -->
{% load customer_filters %}
{% load customer_tags %}    #同样需要导入自定义标签customer_tages文件
{% block title %}
    <title>首页面</title>
{% endblock %}
{% block link %}
    <link rel="stylesheet" href="{% static 'teacher/index.css' %}">
{% endblock %}
{% block content %}
    <table>
        <tr>
            <th>序号</th>
            <th>姓名</th>
            <th>年龄</th>
            <th>性别</th>
            <th>选课</th>
        </tr>
        {% for student in students %}
        <tr {% if student.sex == '0' %}style="color:red;"{% endif %}>
            <td><a href="{% url 'teacher:detail' student.name %}">{{ forloop.counter }}</a></td>  <!-- forloop.counter0从0开始计数,没有0则从1开始计数-->
            <td>{{ student.name }}</td>
            <td>{{ student.age }}</td>
            <td>{{ student.sex|to_male:'zh' }}</td>
            {# <td>{{ student.course }}</td> #}
            <td>
            {# 方式1:{% show_list student.course %} #}
            {# 方式2: #}
            {% show_list student.course style='button' %}   #同样的三种方式调用
            {# 方式3:{% show_list style='button' %} #}      
        #第三种方式未演示,参考简单标签模式编写,代码错误无法正常显示,在views.py文件添加context对应项目输出后OK
</td> </tr> {% endfor %} </table> 模板过滤器:{{ lt.0|add:5 }} 模板过滤器:{{ lt|first }} <h3>当前时间:{{ now }}</h3> <h3>当前时间+过滤器:{{ now|date:'Y年m月d日 H:i:s' }}</h3> {# #方式1:<h3>当前时间+自定义模板标签:{% current '%Y年%m月%d日 %H:%M:%S' %}</h3> #} {# #方式2:<h3>当前时间+自定义模板标签:{% current format_str %}</h3> #} {# #方式3: #} <h3>当前时间+自定义模板标签:{% current %}</h3> <h3>{{ format_str }}</h3> {% endblock %}

同简单标签一样,views.py文件中需要对context输出项目进行定义

from django.shortcuts import render, redirect, reverse
from django.http import HttpResponse
from datetime import datetime

def index(request):
    now = datetime.now()
    #now = now.strftime('%Y年%m月%d日 %H:%M:%S')  #对时间呈现方式进行格式化
    format_str = '%Y年%m月%d日 %H:%M:%S'
    lt = [1, 2, 3]
    dt = {'name': 'tiger', 'age': 18}
    js = '<script>alert("1")</script>'
    html = '<h1>我是安全的</h1>'
    students =[
        {'name':'tager', 'age':18, 'sex':'1', 'course':['python', 'music', 'java', '前端']},
        {'name': 'liuda', 'age': 19, 'sex': '0', 'course':['python', 'music', 'java', '前端']},
        {'name': 'lier', 'age': 20, 'sex': '1', 'course':['python', 'music', 'java', '前端']},
        {'name': 'zhangsan', 'age': 18, 'sex': '0', 'course':['python', 'music', 'java', '前端']},
        {'name': 'wangwu', 'age': 21, 'sex': '1', 'course':['python', 'music', 'java', '前端']},
    ]
    for i in students:
        value = i['course']
    def func():
        return '函数'

    return render(request, 'teacher/index.html', context={
        'now': now,
        'lt': lt,
        'dt': dt,
        'func': func,
        'js': js,
        'html': html,
        'students': students,
        'format_str': format_str,
        'value': value
    })

4. 引用上下文变量

  a. format_str:在views.py定义---->通过context传递到模板文件---->通过自定义模板标签传递到自定义模板标签函数

  b. takes_context=True 实现从views.py中context中获取需要的变量,第一个参数必须是context,且takes_context必须为True

 

总结:

1. 可以接受任意位置、关键字参数

2. 通过空格分离

3. 简单标签:return什么页面直接展示什么

4. 包含标签:接受数据,把数据通过另一个模板进行渲染后再返回回来,哪里调用,哪里显示。

posted on 2022-11-03 16:05  興華  阅读(82)  评论(0编辑  收藏  举报