本文转载自https://blog.csdn.net/xiaogeldx/article/details/87869624
关于自定义
- 代码布局(自定义的代码放在那里)
- 某个app特有的
- app目录下创建templatetags(Python的包)(名字固定的)文件夹
- 把普通文件夹变成Python的包:在文件夹中加__init__.py
- 在templatetags文件夹下创建Python模块(py文件)
- 定义复用
- 创建一个新的app,将他们定义在新的app中,在INSTALL_APPS注册,然后就可以应用
- app特有的和复用的只是代码布局(代码所在文件夹)不同,没有什么区别
- 某个app特有的
- templates存放模板的目录
- templatetags存放自定义标签及过滤器的目录
templatetags这个目录名字是固定的,而里面的模块名是自定义的
自定义模板过滤器
- 模板过滤器本质是函数
- 有一个或两个参数,返回字符串
- 第一个参数是传递进来的模板变量
- 第二个参数是普通的参数,也可以是默认,也可以不要
- 定义非常简单,就是写一个函数,一个带有一个或两个参数的Python参数:
- (输入的)变量的值不一定是字符串形式
- 参数的值可以有一个初始值,或者完全不要这个参数
注册自定义过滤器
- 注册自定义过滤器有两种方法:
- 通过django.template.Library的实例的filter方法
django.template.Library.filter()- Library.filter()方法需要两个参数:
- name 过滤器的名称(一个字符串对象),可以不写,默认使用方法名作为过滤器的名称
- filter_func(定义的过滤器的函数),一个Python函数(不要把函数名写成字符串)
- Library.filter()方法需要两个参数:
- 也可以把register.filter()用做装饰器
- 可以传name参数,也可以不传
- 通过django.template.Library的实例的filter方法
- 没有声明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)