zoukankan      html  css  js  c++  java
  • 自定义过滤器及标签

    本文转载自https://blog.csdn.net/xiaogeldx/article/details/87869624

    关于自定义

    • 代码布局(自定义的代码放在那里)
      • 某个app特有的
        • app目录下创建templatetags(Python的包)(名字固定的)文件夹
        • 把普通文件夹变成Python的包:在文件夹中加__init__.py
        • 在templatetags文件夹下创建Python模块(py文件)
      • 定义复用
        • 创建一个新的app,将他们定义在新的app中,在INSTALL_APPS注册,然后就可以应用
      • app特有的和复用的只是代码布局(代码所在文件夹)不同,没有什么区别
    • templates存放模板的目录
    • templatetags存放自定义标签及过滤器的目录
      templatetags这个目录名字是固定的,而里面的模块名是自定义的

    自定义模板过滤器

    • 模板过滤器本质是函数
    • 有一个或两个参数,返回字符串
      • 第一个参数是传递进来的模板变量
      • 第二个参数是普通的参数,也可以是默认,也可以不要
    • 定义非常简单,就是写一个函数,一个带有一个或两个参数的Python参数:
      • (输入的)变量的值不一定是字符串形式
      • 参数的值可以有一个初始值,或者完全不要这个参数

    注册自定义过滤器

    • 注册自定义过滤器有两种方法:
      • 通过django.template.Library的实例的filter方法
        django.template.Library.filter()
        • Library.filter()方法需要两个参数:
          • name 过滤器的名称(一个字符串对象),可以不写,默认使用方法名作为过滤器的名称
          • filter_func(定义的过滤器的函数),一个Python函数(不要把函数名写成字符串)
      • 也可以把register.filter()用做装饰器
        • 可以传name参数,也可以不传
    • 没有声明name参数,Django将使用函数名作为过滤器的名字

    使用自定义过滤器

    • 在模板中使用自定义的过滤器
    • 需要使用{% load 模块名 %}标签将我们的自定义的模块加载进来
    • {% load 模块名 %}声明将会载入给定模块名中的标签/过滤器

    案例

    • views.py中的index代码:

        def index(request):
            students = [
            {'id':10, 'name': '小哥', 'age': 15, 'gender': 1},
            {'id':33,'name': 'yang', 'age': 15, 'gender': 0},
            {'id':53,'name': 'wen', 'age': 25, 'gender': 0},
            {'id':12,'name': 'long', 'age': 18, 'gender': 1},
            {'id':76,'name': 'na', 'age': 16, 'gender': 0},
            {'id':38,'name': 'yi', 'age': 19, 'gender': 0},
            {'id':48,'name': 'xin', 'age': 17, 'gender': 1},
            ]
            return render(request, 'students/index.html', context={
                'students': students,
            })
      
    • index.html的demo:

        {% extends 'students/base.html' %}
        {% block title %}学生表{% endblock %}
        {% load static %}
        {% load customer_filters %}
        {% block link %}<link href="{% static 'students/css/index.css' %}" rel="stylesheet">{% endblock %}
        {% block content %}
            <div class="blog-masthead">
              <div class="container">
                <nav class="blog-nav">
                  <a class="blog-nav-item active" href="#">Home</a>
                  <a class="blog-nav-item" href="#">New features</a>
                  <a class="blog-nav-item" href="#">Press</a>
                  <a class="blog-nav-item" href="#">New hires</a>
                  <a class="blog-nav-item" href="#">About</a>
                </nav>
              </div>
            </div>
            <div class="container">
              <div class="blog-header">
                {#  从这里开始替换#}
                <table class="table">
                    <tr>
                        <th>序号</th>
                        <th>姓名</th>
                        <th>年龄</th>
                        <th>性别</th>
                    </tr>
                {#  如果students为空,则渲染empty下的内容#}
                    {% for stu in students %}
                        <tr {% if stu.age < 17 %}style="color:blue;"
                            {% elif stu.age > 16 and stu.age < 22 %}style="color:red;"
                            {% else %}style="color:green;"
                            {% endif %}>
                {#        forloop.counter获取当前for循环的迭代次数,以1开始#}
                {# 硬编码跳转  <td><a href="/students/detail/{{ stu.id }}/">{{ forloop.counter }}</a></td>#}
                            <td><a href="{% url 'students:detail' stu.id %}">{{ forloop.counter }}</a></td>
                {#        forloop.counter0获取当前for循环的迭代次数,以0开始#}
                {#            <td>{{ forloop.counter0 }}</td>#}
                {#        forloop.revcounter获取当前for循环的迭代次数,从大到小#}
                {#            <td>{{ forloop.revcounter }}</td>#}
                {#        forloop.revcounter0获取当前for循环的迭代次数,从大到小,最小为0#}
                {#            <td>{{ forloop.counter0 }}</td>#}
                            <td>{{ stu.name }}</td>
                            <td>{{ stu.age }}</td>
                  {#to_male对应customer_filter.py的@register.filter的name名对应#}
                            <td>{{ stu.gender|to_male:'en' }}</td>	
                        </tr>
                {#  如果students为空,则渲染empty下的内容#}
                {#          {% empty %}#}
                {#          要渲染的内容#}
                    {% endfor %}
                </table>
              </div>
            </div><!-- /.blog-sidebar -->
            <div style="position:fixed; bottom:0px;">
            {#  将渲染好的模板放到想要放的模板#}
                {% include 'students/ad.html' %}
            </div>
        {% endblock %}
        {% block domready %}
            <script src="https://cdn.bootcss.com/jquery/1.12.4/jquery.min.js"></script>
            <script>window.jQuery || document.write('<script src="../../assets/js/vendor/jquery.min.js"></script>')</script>
            <script src="https://cdn.bootcss.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
        {% endblock %}
      
    • customer_filter.py的demo:

        from django.template import Library
        register = Library()
        # @register.filter()	#和下一行的区别是下一行可以定义name名
        #自定义过滤器的第二种方法
        @register.filter(name='to_male')	#'to_male'对应{{ stu.gender }}的to_male
        def to_male(value, arg='zh'):    #默认是中文
            map = {
                'zh': ('女', '男'),
                'en': ('female', 'male')
            }
            # if value == 0:
            #     if arg == 'zh':
            #         return '女'
            #     return 'female'
            # if value == 1:
            #     if arg == 'zh':
            #         return '男'
            #     return 'male'
            return map[arg][value] 	#等同于上几行注释掉的demo
        #下面三行注释掉的是一样的效果,是注册自定义过滤器的第一种方法
        # register.filter('to_male', to_male)
        # register.filter(to_male)
        # register.filter(name='to_male', filter_func=to_male)
      

      效果图:
      在这里插入图片描述

    自定义模板标签

    简单标签

    	django.template.Labrary.simple_tag()
    
    • 新建Python模块
      • 在templatetags中创建py文件,customer_tags.py
    • 注册
      • 调用函数
      • 装饰器
    • 引用上下文变量(views中render传递到模板中的那个context)
      • 只需要在simple_tag中,设置参数take_context=True
      • 自定义的标签函数的第一个参数一定是context
    • 使用自定义模板标签
      • 需要使用{% load 模块名 %}标签将我们的自定义的模块加载进来

    demo

    • views.py的代码:

        format_str = '%Y-%m-%d %H:%M:%S'
            return render(request, 'students/index.html', context={
                'students': students,
                'format_str': format_str,
            })
      
    • index.html的代码:

        {% load customer_tags %}	#在开头
        <h1>当前时间:{% current %}</h1>		#在正文部分
      
    • customer_tags的代码:

        from django.template import Library
        from datetime import datetime
        register = Library()
        @register.simple_tag(name='current', takes_context=True)    #注册,装饰器
        def current_time(context):  #context必须是第一个参数,并且名字固定,不能改
            return datetime.now().strftime(context['format_str'])
        # register.simple_tag(current_time, name='current') #注册,调用函数
      

    包含标签

    	django.template.Library.inclusion_tag()
    
    • 通过渲染另外一个模板来展示数据,类似url中的include

    定义

    • 在customer_tags模板中定义一个函数,接受调用时传递的模板变量

        @register.inclusion_tag('students/show_list_as_ul.html')    #参数是想要传的模板
        def show_list_as_ul(value, style):
            return {'ls': value, 'style': style}
        # registerinclusion_tag('students/show_list_as_ul.html')(show_list_as_ul)
      
    • 定义一个模板

    • tag()方法有两个参数:

      • 模板标记的名称是字符串,如果省略,将使用编译函数的名称
      • 编译的函数是一个Python函数(不要把函数名写成字符串)
      • 和简单标签注册一样,也可以将其用做装饰器
      • 也可以拿到context,和简单标签用法一样
    • 包含标签的功能是可以通过渲染另外一个模板来显示一些数据

    • 很多地方都可能会用到下面这几行代码,除了choices(模板变量)这几个变量不一样之外,其他的都是格式都一样时,那么我们就可以把这部分代码封装在一个包含标签中

        <ul>
            {% for i in choices %}
            <li>{{ i }}</li>
            {% endfor %}
        </ul>
      

    案例

    • show_list_as_ul.html的代码:

        {% if style == 'button' %}
            <div class="list-group">
            {% for l in ls %}
                 <button type="button" class="list-group-item">{{ l }}</button>
            {% endfor %}
            </div>
        {% elif style == 'link' %}
            <div class="list-group">
            {% for l in ls %}
                <a href="#" class="list-group-item active">{{ l }}</a>
            {% endfor %}
            </div>
        {% else %}
            <ul class="list-group">
            {% for l in ls %}
                <li class="list-group-item">{{ l }}</li>
            {% endfor %}
            </ul>
        {% endif %}
      
    • index.html的部分代码:

        {#                    <td>{% show_list_as_ul stu.course 'link' %}</td>#}
        {#                    等同于上行代码#}
        {#                    <td>{% show_list_as_ul stu.course style='link' %}</td>#}
        {#                    <td>{% show_list_as_ul stu.course 'button' %}</td>#}
                            <td>{% show_list_as_ul stu.course '' %}</td>
      
    • customer_tags.py的部分代码:

        @register.inclusion_tag('students/show_list_as_ul.html')    #参数是想要传的模板路径
        def show_list_as_ul(value, style):
            return {'ls': value, 'style': style}
        # registerinclusion_tag('students/show_list_as_ul.html')(show_list_as_ul)
  • 相关阅读:
    bzoj1505 [NOI2004]小H的小屋
    最大值
    数学
    OI中的快速傅里叶变换(FFT)
    旅游规划
    加分二叉树
    浅谈 字符串hash
    二分的弟弟“三分”
    Trie树(c++)
    克鲁斯卡尔
  • 原文地址:https://www.cnblogs.com/xiaogeldx/p/10424943.html
Copyright © 2011-2022 走看看