• 创建tag方式,首先在需要使用tag的app下创建一个templatetags的python包,
  • 然后在包里创建一个tag模块,例如hellotag.py
from django import template

register = template.Library()  # 注意,这里的变量名一定是register,可不是任意的名称

@ register.simple_tag
def hello(*args):
return "hello " + " ".join(str(args))

然后就可以在需要使用tag的页面引用自定义tag了

{% load hellotag %}
{% hello "world !" %}

然后需要重启Django服务,再通过页面测试结果

  • 为什么只能是register,因为Django源码里就是这么解析的
def get_package_libraries(pkg):
"""
Recursively yield template tag libraries defined in submodules of a
package.
"""
for entry in walk_packages(pkg.__path__, pkg.__name__ + '.'):
try:
module = import_module(entry[1])
except ImportError as e:
raise InvalidTemplateLibrary(
"Invalid template library specified. ImportError raised when "
"trying to load '%s': %s" % (entry[1], e)
) if hasattr(module, 'register'):
yield entry[1]
  • 为什么需要重启tag才生效?因为Django在第一次启动时就将一些不易变动的模块代码使用缓存方式的装饰器将这些模块缓存起来了,这样方便加快响应速度,而不是每次返回给用户页面时都重新加载一次tag模块,那样每个用户每访问一个页面,都重新导入一次响应肯定会很慢
  • Django默认会加载以下tag模块
'django.template.defaulttags',
'django.template.defaultfilters',
'django.template.loader_tags',

通过settings指定tag模块

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.i18n',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
'cloud.api.libs.context_processors.common_processor',
],
'autoescape': True,
'debug': settings.DEBUG, # 该值就是我们自定义的settings模块的debug变量值。
'file_charset': settings.FILE_CHARSET, # 这个settings是从全局的Django settings导入的,默认为"utf-8"
'libraries': {} # 这里是字典类型的tag模块名称,例如:项目cloud目录下有一个show.py tag模块,那么完整的模块路径为cloud.show,定义到这个字典的格式为{'show': 'cloud.show'}
},
},
]

注意: TEMPLATES这个列表里的每一个字典元素的key只能是这几个,不能多,也不能少,OPTIONS这个key对应的字典元素里面的key,除了context_processors 以外,其余值都可以不写,默认自带的配置已经有context_processors 了,如果需要自定义其它位置的tag模块,可以添加libraries 这个选项

  • render处理过程

# view方法通过render方法返回模版,如return render(request, 'index.html', context=None, content_type=None, status=200, using=None) # 首先调用render方法,传入参数 # render再调用render_to_string方法去获取模版,并渲染模版,返回一个字符串 # 我们假设只传了一个模版文件的情况,那样的话render_to_string就会调用get_template方法获取指定的模版文件 # get_template 首先通过_engine_list获取到模版引擎 # _engine_list通过EngineHandler的实例化对象得到settings.TEMPLATES的所有模版引擎相关的信息 # EngineHandler在程序启动时就将模版引擎缓存起来了,不过这里还是先说下它的过程,由于对象本身实现了iter方法,所有我们对数据进行迭代时,会触发该方法
# 然后找到对象的templates属性,该属性通过获取settings.TEMPLATES这个列表形式的模版引擎信息,可以有多个模版引擎,每一个引擎都是字典形式存在,且必须
#包含那些KEY,并保存一个副本,将每个引擎的`BACKEND`KEY值以点形式从右开始分割2次,取倒数第二个元素为引擎的名称,这样默认的引擎,名称就是django。
# 然后设置引擎的NAME、DIRS、APP_DIRS、OPTIONS的值,最终所有的模版引擎以字典形式返回,KEY为引擎的名称 # _engine_list调用EngineHandler对象的all方法,all方法通过列表推导遍历self对象本身,也就是在调用__iter__方法,并使用self[alias]这种语法糖形式,
# 实际调用的就是self本身实现的__getitem__方法,将值取出来,每个alias就是上面所分析的所有以KEY方法存到字典的模版引擎,通过__getitem__传入该KEY,再调用
# self.templates[alias]方式,self.templates本身返回的是一个有序字典,所有可以这么取字典的值。通过这样就可以得到每个模版引擎的信息。__getitem__每
# 获取到一个引擎信息时,都将BACKEND对应的值的字符串形式的的模块名通过import_string方法导入该具体的模块,并将得到的模块返回,这里的默认引擎为
# django.template.backends.django.DjangoTemplates,import_string导入时会先导入模块,再获取模块的属性DjangoTemplates,然后返回该属性。
# 接着__getitem__通过得到的DjangoTemplates,进行实例化,并把这个引擎相关的信息参数形式传入。 # _engine_list得到的就是一个包含所有模版引擎的对象,这里实际上就是DjangoTemplates对象, # get_template在遍历_engine_list返回的每一个引擎,然后调用引擎的get_template方法,并把模版名称传入。 # DjangoTemplates实例化时,会将所有APP下的templatetags模块下的tag加载。每个tag必须包含`register`这个属性,也就是你定义tag装饰器时,取的名称必须
# 是register = Library(),名字不能随意,否则不会加载这种tag, # 这些tag都赋值给libraries每个模版的引擎的option的key值。通过settings也可以手动指定其它位置的tag模块, # 还将这些参数传递给Engine进行实例化,还记得平时我们的模版不引用tag也有一些默认tag可用么,其实就是这时导入了一些默认的tag,并赋值给对象的template_builtins。
# 默认的default_builtins = [
# 'django.template.defaulttags',
# 'django.template.defaultfilters',
# 'django.template.loader_tags',
# ]
def render(request, template_name, context=None, content_type=None, status=None, using=None):
content = render_to_string(template_name, context, request, using=using)
return HttpResponse(content, content_type, status) def render_to_string(template_name, context=None, request=None, using=None):
"""
Loads a template and renders it with a context. Returns a string. template_name may be a string or a list of strings.
"""
if isinstance(template_name, (list, tuple)):
template = select_template(template_name, using=using)
else:
template = get_template(template_name, using=using)
return template.render(context, request) def get_template(template_name, using=None):
"""
Loads and returns a template for the given name. Raises TemplateDoesNotExist if no such template exists.
"""
chain = []
engines = _engine_list(using)
for engine in engines:
try:
return engine.get_template(template_name)
except TemplateDoesNotExist as e:
chain.append(e) raise TemplateDoesNotExist(template_name, chain=chain) def _engine_list(using=None):
return engines.all() if using is None else [engines[using]] class EngineHandler(object):
def __init__(self, templates=None):
"""
templates is an optional list of template engine definitions
(structured like settings.TEMPLATES).
"""
self._templates = templates
self._engines = {} @cached_property
def templates(self):
if self._templates is None:
self._templates = settings.TEMPLATES templates = OrderedDict()
backend_names = []
for tpl in self._templates:
tpl = tpl.copy()
try:
# This will raise an exception if 'BACKEND' doesn't exist or
# isn't a string containing at least one dot.
default_name = tpl['BACKEND'].rsplit('.', 2)[-2]
except Exception:
invalid_backend = tpl.get('BACKEND', '<not defined>')
raise ImproperlyConfigured(
"Invalid BACKEND for a template engine: {}. Check "
"your TEMPLATES setting.".format(invalid_backend)) tpl.setdefault('NAME', default_name)
tpl.setdefault('DIRS', [])
tpl.setdefault('APP_DIRS', False)
tpl.setdefault('OPTIONS', {}) templates[tpl['NAME']] = tpl
backend_names.append(tpl['NAME']) counts = Counter(backend_names)
duplicates = [alias for alias, count in counts.most_common() if count > 1]
if duplicates:
raise ImproperlyConfigured(
"Template engine aliases aren't unique, duplicates: {}. "
"Set a unique NAME for each engine in settings.TEMPLATES."
.format(", ".join(duplicates))) return templates def __getitem__(self, alias):
try:
return self._engines[alias]
except KeyError:
try:
params = self.templates[alias]
except KeyError:
raise InvalidTemplateEngineError(
"Could not find config for '{}' "
"in settings.TEMPLATES".format(alias)) # If importing or initializing the backend raises an exception,
# self._engines[alias] isn't set and this code may get executed
# again, so we must preserve the original params. See #24265.
params = params.copy()
backend = params.pop('BACKEND')
engine_cls = import_string(backend)
engine = engine_cls(params) self._engines[alias] = engine
return engine def __iter__(self):
return iter(self.templates) def all(self):
return [self[alias] for alias in self] engines = EngineHandler() class DjangoTemplates(BaseEngine): app_dirname = 'templates' def __init__(self, params):
params = params.copy()
options = params.pop('OPTIONS').copy()
options.setdefault('autoescape', True)
options.setdefault('debug', settings.DEBUG)
options.setdefault('file_charset', settings.FILE_CHARSET)
libraries = options.get('libraries', {})
options['libraries'] = self.get_templatetag_libraries(libraries)
super(DjangoTemplates, self).__init__(params)
self.engine = Engine(self.dirs, self.app_dirs, **options) def from_string(self, template_code):
return Template(self.engine.from_string(template_code), self) def get_template(self, template_name):
try:
return Template(self.engine.get_template(template_name), self)
except TemplateDoesNotExist as exc:
reraise(exc, self) def get_templatetag_libraries(self, custom_libraries):
"""
Return a collation of template tag libraries from installed
applications and the supplied custom_libraries argument.
"""
libraries = get_installed_libraries()
libraries.update(custom_libraries)
return libraries

django的templatetags的更多相关文章

  1. 2 django系列之django分页与templatetags

    preface 当页面出现的条目多的时候,我们就需要使用分页功能了.Django作为一个知名的web框架,自然也提供了分页功能,下面说说它. Python-shell 练练手 在python下入手 先 ...

  2. django分页功能,templatetags的应用

    django 将不会将得到的html代码自动转化 from django.utils.html import format_html html =''' <a href='http://www. ...

  3. Django 自定义标签与过滤器报错 No module named 'templatetags'

    Django 自定义标签与过滤器报错 按照网上的教程如果想使用自定义的标签与过滤器就得往settings.py中添加下列数据 TEMPLATES = [ { 'BACKEND': 'django.te ...

  4. Django 自定义模板标签TemplateTags

    创建自定义的模板标签(template tags) Django提供了以下帮助函数(functions)来允许你以一种简单的方式创建自己的模板标签(template tags): simple_tag ...

  5. 《Django By Example》第三章 中文 翻译 (个人学习,渣翻)

    书籍出处:https://www.packtpub.com/web-development/django-example 原作者:Antonio Melé (译者注:第三章滚烫出炉,大家请不要吐槽文中 ...

  6. Django

    一.Django 简介 Django 是一个由 Python 写成的开放源代码的 Web 应用框架.它最初是被开发来用于管理劳伦斯出版集团旗下的一些以新闻内容为主的网站的,即是 CMS(内容管理系统) ...

  7. python框架之django

    python框架之django 本节内容 web框架 mvc和mtv模式 django流程和命令 django URL django views django temple django models ...

  8. Django基础之安装配置

    安装配置 一 MVC和MTV模式 著名的MVC模式:所谓MVC就是把web应用分为模型(M),控制器(C),视图(V)三层:他们之间以一种插件似的,松耦合的方式连接在一起. 模型负责业务对象与数据库的 ...

  9. Python 【第十一章】 Django模版

    1.直接传值 urls.py """mysite URL Configuration The `urlpatterns` list routes URLs to view ...

随机推荐

  1. IIS 无法显示网页 目前访问网站的用户过多

    最近把一个服务部署到XP系统的IIS上,供其他程序调用,在访问了几个页面后,会出现“无法显示网页 目前访问网站的用户过多”的提示. 网上找了,果然有解决方法: 1.打开IIS,在网站上右键,选择“属性 ...

  2. Python_部分内置函数

    内置函数:可以直接调用的函数 all():传入的列表,元组,等等,只要一个为假,就为假(fales)(所有的都为真才为真) # None, {}:空字典, []:空列表, 0:零,():空集合,“”: ...

  3. window与linux文件共享解决方案

    我的系统是windows7 x64,虚拟机上的linux系统是centos6.5 方法一: 1.在win7系统上建立一个用户 2.在f盘建立一个文件夹linuxshare,然后右击-属性-共享-高级共 ...

  4. JMeter中BeanShell断言使用一

    Jmeter Ant Task如何让beanshell断言失败的详细信息展示在report里面 首先必须给beanshell断言添加FailureMessage if(${TotalClient_SS ...

  5. Flink运行在yarn上

    在一个企业中,为了最大化的利用集群资源,一般都会在一个集群中同时运行多种类型的 Workload.因此 Flink 也支持在 Yarn 上面运行: flink on yarn的前提是:hdfs.yar ...

  6. Codeforces Gym100543B 计算几何 凸包 线段树 二分/三分 卡常

    原文链接https://www.cnblogs.com/zhouzhendong/p/CF-Gym100543B.html 题目传送门 - CF-Gym100543B 题意 给定一个折线图,对于每一条 ...

  7. .netcore加入APM系统 SkyWalking

    安装环境:windows 2016 必要条件: JDK8+ Elasticsearch 5.x(注:目前不支持es6) 8080,10800,11800,12800 端口不被占用 下载skywalki ...

  8. Shiro笔记(六)Shiro标签的使用

    Shiro标签的使用 引入标签库 <%@taglib prefix="shiro" uri="http://shiro.apache.org/tags"% ...

  9. sql语句表示不等于

    <> != 后面均不带引号“”

  10. 解决每次调试网页,eclipse总是提示edit source lookup path的问题,我的第一篇小随笔,小激动呢

    如图,很简单,只要把想要debug的项目勾上就行,网页调试时,就会自动去找项目文件位置