Django进阶——高级模板

一、上下文管理

  • 阶段一:原始方法,手动构造上下文
 from django.template import loader, Context

 def view_1(request):
    #载入模板
    t = loader.get_template('template1.html')
    #手动构建上下文
    c = Context({
        'app': 'My app',
        'user': request.user,
        'ip_address': request.META['REMOTE_ADDR'],
        'message': 'I am view 1.'
        })
    #渲染模板并返回
    return t.render(c)
  • 阶段二:优化,使用上下文管理器
from django.shortcuts import render
from django.template import RequestContext
#定义上下文管理器
def custom_proc(request):
    return {
            'app': 'My app',
            'user': request.user,
            'ip_address': request.META['REMOTE_ADDR']
            }

def view_1(request):
    return render(request, 'template1.html',
        {'message': 'I am view 1.'},
        context_instance = RequestContext(request, processors=[custom_proc])
        )
  • 最终版:Django提供全局上下文管理器
    Django 提供了全局上下文处理 器。context_processors 设置(在 settings.py 文件中)指明始终提供给 RequestContext 的上下文处理器。 这样便不用每次使用 RequestContext 时都指定 processors 参数了。
from django.shortcuts import render

def view_1(request):
    return render(request, 'template1.html',{'message': 'I am view 1.'})
  • 自定义上下文处理器

上下文处理器的接口十分简单,它就是普通的 Python 函数,有一个参数,是一个 HttpRequest 对象,返回一 个字典,用于添加到模板上下文中。上下文处理器必须返回一个字典。
-
自定义的上下文处理器可以放在代码基的任何位置。Django 只关心 TEMPLATES 设置中的 ‘con- text_processors’ 选项或者 Engine 的 context_processors 参数(直接使用 Engine 时)有没有指向你 的上下文处理器。尽管如此,约定的做法是把上下文处理器保存在应用或项目中一个名为 con- text_processors.py 的文件中。

二、模板加载机制

Django 在多个位置搜索模板目录,具体是哪些取决于模板加载设置,指定模板目录最基本的方式是使用 DIRS 选项。DIRS告诉 Django 模板目录有哪些的方法是使用设置文件中 TEMPLATES 设置的 DIRS 选项,或者是 Engine 的 dirs 参数。这个选项的值是一个字符串列表,包含指向模板目录的完整路径

  • myblog/settings.py
TEMPLATES = [
        {
            'BACKEND': 'django.template.backends.django.DjangoTemplates',
             # 系统加载,'DIRS'是一个字符串列表,包含指向模板目录的完整路径
            'DIRS': [ 
                os.path.join(BASE_DIR, 'templates'),
            ],
            # 应用目录加载 自动查找/myblogs/books/templtates下的模板
            'APP_DIRS': True,
}, ]

三、扩展模板系统

对模板系统的定制,基本上是自 定义模板标签和(或)过滤器。
-
自定义的模板标签和过滤器必须放在一个 Django 应用中。如果与现有应用有关,可以放在现有应用中;否 则,应该专门创建一个应用存放。应用中应该有个 templatetags 目录,与 models.py、views.py 等文件放在 同一级。如果没有这个目录,创建一个,别忘了 init.py 文件,这样才能保证所在目录是一个 Python 包.

代码布局
  • 创建模板标签和过滤器

假如自定义的标签(过滤器)放在 review_extras.py 文件中,应用的布局可能是下面这样:

books/
    __init__.py
    models.py
    templatetags/
        __init__.py
        review_extras.py
    views.py
  • 在模板中使用
{% load review_extras %}

包含自定义标签的应用必须在 INSTALLED_APPS 中列出,这样 {% load %} 标签才能起作用。

自定义模板过滤器实例
  • 定义并注册过滤器:myblog/books/templatetags/review_extras.py

方式一:

from django import template
register = template.Library()

#定义过滤器函数
def cut(value, arg):
    """Removes all values of arg from the given string"""
    return value.replace(arg, '')

#注册过滤器:第一个参数为过滤器名,第二个参数为对应的函数
register.filter('cut', cut)
register.filter('lower', lower)

方式二:

from django import template
register = template.Library()

@register.filter
def cut(value, arg):
    """Removes all values of arg from the given string"""
    return value.replace(arg, '')
  • 使用
{{ value|cut:"arg" }}
  • 定义期待字符串的模板过滤器时,需使用@stringfilter
from django import template
from django.template.defaultfilters import stringfilter
register = template.Library()

@register.filter
@stringfilter   #参数在传给过滤器之前会先转换成字符串值
def lower(value):
    return value.lower()
  • 定义处理 datetime 对象的过滤器时,需使设置expects_localtime 旗标参数为 True
@register.filter(expects_localtime=True)
def businesshours(value):
    try:
        return 9 <= value.hour < 17
    except AttributeError:
        return ''
自定义模板标签


  • 一、简单实例

current_time 标签,它接受一个格式字符串,返回格式化后的时间字符串

import datetime
from django import template
register = template.Library()

@register.simple_tag
def current_time(format_string):
    return datetime.datetime.now().strftime(format_string)
  • 二、模板标签需要使用上下文

如果模板标签需要访问当前上下文,注册标签时指定 takes_context 参数:

@register.simple_tag(takes_context=True)
def current_time(context, format_string):
    timezone = context['timezone']
    return your_get_current_time_method(timezone, format_string)
  • 三、为标签起别名
方式一:
register.simple_tag(lambda x: x - 1, name='minusone')

方式二:
@register.simple_tag(name='minustwo')
def some_function(value):
    return value - 2
  • 四、接收参数

定义标签

@register.simple_tag
def my_tag(a, b, *args, **kwargs):
    warning = kwargs['warning']
    profile = kwargs['profile']
    ...
    return ...

使用

{% my_tag 123 "abcd" book.title warning=message|lower profile=user.profile %}
  • 五、引入标签(模板标签用于渲染另一个模板)

需求:编写一个标签,生成指定Author 对象名下的图书列表

#使用:
{% books_for_author author %}

#结果:
<ul>
    <li>The Cat In The Hat</li>
    <li>Hop On Pop</li>
    <li>Green Eggs And Ham</li>
</ul>

实现:

#定义一个接受参数的函数,生成一个字典,为结果提供数据
def books_for_author(author):
    books = Book.objects.filter(authors__id=author.id)
    return {'books': books}

books/templates/book_snippet.html

#创建用于渲染标签输出的模板,需放在模板目录下
<ul>
    {% for book in books %}
    <li>{{ book.title }}</li>
    {% endfor %}
</ul>
#创建并注册引入标签
@register.inclusion_tag('book_snippet.html')
def show_reviews(review):
    ...
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值