码农行者 码农行者
首页
  • Python

    • 语言特性
    • Django相关
    • Tornado
    • Celery
  • Golang

    • golang学习笔记
    • 对比python学习go
    • 模块学习
  • JavaScript

    • Javascript
  • 数据结构预算法笔记
  • ATS
  • Mongodb
  • Git
云原生
运维
垃圾佬的快乐
  • 数据库
  • 机器学习
  • 杂谈
  • 面试
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

DeanWu

软件工程师
首页
  • Python

    • 语言特性
    • Django相关
    • Tornado
    • Celery
  • Golang

    • golang学习笔记
    • 对比python学习go
    • 模块学习
  • JavaScript

    • Javascript
  • 数据结构预算法笔记
  • ATS
  • Mongodb
  • Git
云原生
运维
垃圾佬的快乐
  • 数据库
  • 机器学习
  • 杂谈
  • 面试
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • Django 最佳实践-读书笔记 - 第十三章 模板最佳实践

    • 尽量保持大多数的模板文件在目录 templates/ 下
      • 模板的架构模式
        • 2 层嵌套模式
        • 3 层嵌套模式
        • 扁平比嵌套好
      • 在模板中限制逻辑处理
        • 当在模板中遍历结果集时注意的问题:
        • 在使用 cache 之前,尝试优化,重构你的代码
        • 保持模板简单,尽量少使用 js 或 filter 来处理数据,这样会拖慢你的页面
        • 不要在模板中的结果集中遍历查询对象
        • 不要在模板中隐含复杂的查询
        • 模板尽量避免加载导致cpu使用过高的对象
        • 不要在模板中调用 rest api
      • 使用缩进来使你的模板更加易读
        • block.super 的使用,来更好的使用继承特性
          • 一些有用的技巧
            • 样式的控制和 python的要松耦合
            • 一些通用的约定
            • 使用具体的 model 对象名来命名模板对象列表
            • 使用 url 名字来代替硬编码的url
            • debug 的时候可以开启,页面详细错误
          • 错误模板的设置
            • filter 什么时候使用
              • 自定义 tags
                • 命名 tags 类库
                  • 在 template 页面中加载 tags
                    • 不同之处
                      • 我们应该如何选择
                        • DTL 的优点
                        • jinjia2 的优点
                        • 如何选择
                      • jinja2 部分使用举例
                        • CSRF
                        • jinja2 无法使用 自定义 tags的
                        • jinja2 中使用 django-style 的 filter
                        • 上下文 context 不能在 jinja2 中使用
                    • 开发语言
                    • Python
                    • Best.Practices.for.Django
                    DeanWu
                    2016-07-02
                    目录

                    Django 最佳实践-读书笔记 - 第十三章 模板最佳实践

                    其他章节索引页

                    笔记以要点形式展开,如有疑问欢迎留言!

                    # 第十三章 模板最佳实践

                    django 的模板的局限性,限制了我们将复杂的逻辑放在了 python 端,这何尝不是一件好事。

                    从 django 1.8 开始,django 原生支持了 jinjia2 模板。

                    # 尽量保持大多数的模板文件在目录 templates/ 下

                    templates/
                        base.html
                        ... (other sitewide templates in here)
                        freezers/ ("freezers" app templates in here)
                    
                    1
                    2
                    3
                    4

                    将模板放在 app 下 templates 是没有必要的,因为当app 作为可拔插的包拿来使用的时候,它的模板会被重新设计。 索性将所有app 模板放到templates 下,好维护些。

                    # 模板的架构模式

                    # 2 层嵌套模式

                    2 层嵌套模式适合于全站统一布局的情况。

                    templates/
                    base.html
                    dashboard.html # extends base.html
                        profiles/
                            profile_detail.html # extends base.html
                    
                    1
                    2
                    3
                    4
                    5

                    # 3 层嵌套模式

                    3 层嵌套适合于每个app 需要自己的布局的情况。

                    templates/
                    base.html
                    dashboard.html # extends base.html
                        profiles/
                            base_profiles.html # extends base.html
                            profile_detail.html # extends base_profiles.html
                            profile_form.html # extends base_profiles.html
                    
                    1
                    2
                    3
                    4
                    5
                    6
                    7

                    # 扁平比嵌套好

                    # 在模板中限制逻辑处理

                    # 当在模板中遍历结果集时注意的问题:

                    • 不要在模板中遍历巨大的结果集
                    • 检索的对象多大,是不是所有的对象在模板中都需要
                    • 将逻辑处理移出循环,不要重复处理,拖慢循环处理。

                    # 在使用 cache 之前,尝试优化,重构你的代码

                    # 保持模板简单,尽量少使用 js 或 filter 来处理数据,这样会拖慢你的页面

                    # 不要在模板中的结果集中遍历查询对象

                    Bad Example :

                    <h2>Greenfelds Who Want Ice Cream</h2>
                    <ul>
                    {% for voucher in voucher_list %}
                        {# Don't do this: conditional filtering in templates #}
                        {% if "greenfeld" in voucher.name.lower %}
                            <li>{{ voucher.name }}</li>
                        {% endif %}
                    {% endfor %}
                    </ul>
                    <h2>Roys Who Want Ice Cream</h2>
                    <ul>
                    {% for voucher in voucher_list %}
                        {# Don't do this: conditional filtering in templates #}
                        {% if "roy" in voucher.name.lower %}
                            <li>{{ voucher.name }}</li>
                        {% endif %}
                    {% endfor %}
                    </ul>
                    
                    
                    
                    1
                    2
                    3
                    4
                    5
                    6
                    7
                    8
                    9
                    10
                    11
                    12
                    13
                    14
                    15
                    16
                    17
                    18
                    19
                    20

                    Right Exemple:

                    # vouchers/views.py
                    from django.views.generic import TemplateView
                    from .models import Voucher
                    
                    
                    class GreenfeldRoyView(TemplateView):
                        template_name = "vouchers/views_conditional.html"
                        
                        def get_context_data(self, **kwargs):
                            context = super(GreenfeldRoyView, self).get_context_data(**kwargs)
                            context["greenfelds"] = \
                            Voucher.objects.filter(name__icontains="greenfeld")
                            context["roys"] = Voucher.objects.filter(name__icontains="roy")
                            return context
                    
                    1
                    2
                    3
                    4
                    5
                    6
                    7
                    8
                    9
                    10
                    11
                    12
                    13
                    14
                    <h2>Greenfelds Who Want Ice Cream</h2>
                    <ul>
                    {% for voucher in greenfelds %}
                        <li>{{ voucher.name }}</li>
                    {% endfor %}
                    </ul>
                    <h2>Roys Who Want Ice Cream</h2>
                    <ul>
                    {% for voucher in roys %}
                        <li>{{ voucher.name }}</li>
                    {% endfor %}
                    
                    1
                    2
                    3
                    4
                    5
                    6
                    7
                    8
                    9
                    10
                    11

                    # 不要在模板中隐含复杂的查询

                    Bad exemple:

                    {# list generated via User.object.all() #}
                    <h1>Ice Cream Fans and their favorite flavors.</h1>
                    <ul>
                    {% for user in user_list %}
                        <li>
                        {{ user.name }}:
                        {# DON'T DO THIS: Generated implicit query per user #}
                        {{ user.flavor.title }}
                        {# DON'T DO THIS: Second implicit query per user!!! #}
                        {{ user.flavor.scoops_remaining }}
                        </li>
                    {% endfor %}
                    </ul>
                    
                    1
                    2
                    3
                    4
                    5
                    6
                    7
                    8
                    9
                    10
                    11
                    12
                    13

                    Right Exemple:

                    {# 生成列表的时使用: User.object.all().select_related("flavors") #}
                    
                    <h1>Ice Cream Fans and their favorite flavors.</h1>
                    <ul>
                    {% for user in user_list %}
                        <li>
                        {{ user.name }}:
                        {{ user.flavor.title }}
                        {{ user.flavor.scoops_remaining }}
                        </li>
                    {% endfor %}
                    </ul>
                    
                    1
                    2
                    3
                    4
                    5
                    6
                    7
                    8
                    9
                    10
                    11
                    12

                    # 模板尽量避免加载导致cpu使用过高的对象

                    例如图片的加载,尽量使用模板外部的工具。

                    详见:13.3.4 Gotcha 4: Hidden CPU Load in Templates

                    # 不要在模板中调用 rest api

                    当我们在模板中调用 rest api 时,注意:

                    • 在js请求数据,加载时,你需要分散你客户的注意力。
                    • python 处理缓慢的进程方式更多:消息队列,多线程,多进程等。

                    # 使用缩进来使你的模板更加易读

                    # block.super 的使用,来更好的使用继承特性

                    {# simple base.html #}
                    {% load staticfiles %}
                    <html>
                    <head>
                    <title>
                        {% block title %}Two Scoops of Django{% endblock title %}
                    </title>
                        {% block stylesheets %}
                            <link rel="stylesheet" type="text/css"
                            href="{% static "css/project.css" %}">
                        {% endblock stylesheets %}
                    </head>
                    <body>
                        <div class="content">
                            {% block content %}
                                <h1>Two Scoops</h1>
                            {% endblock content %}
                        </div>
                    </body>
                    </html>
                    
                    1
                    2
                    3
                    4
                    5
                    6
                    7
                    8
                    9
                    10
                    11
                    12
                    13
                    14
                    15
                    16
                    17
                    18
                    19
                    20
                    {% extends "base.html" %}
                    {% load staticfiles %}
                    {% block title %}About Audrey and Daniel{% endblock title %}
                    {% block stylesheets %}
                        {{ block.super }}
                        <link rel="stylesheet" type="text/css"
                        href="{% static "css/about.css" %}">
                    {% endblock stylesheets %}
                    {% block content %}
                        {{ block.super }}
                        <h2>About Audrey and Daniel</h2>
                        <p>They enjoy eating ice cream</p>
                    {% endblock content %}
                    
                    1
                    2
                    3
                    4
                    5
                    6
                    7
                    8
                    9
                    10
                    11
                    12
                    13

                    # 一些有用的技巧

                    # 样式的控制和 python的要松耦合

                    # 一些通用的约定

                    • 使用下划线来命名模板名称,block 名称。

                    • block 的名字要清晰,如{% block javascript %}`

                    • 在 block 结束时,也要写上名称,如 {% endblock javascript %}.

                    # 使用具体的 model 对象名来命名模板对象列表

                    {# toppings/topping_list.html #}
                    {# Using implicit names #}
                    <ol>
                        {% for object in object_list %}
                            <li>{{ object }} </li>
                        {% endfor %}
                    </ol>
                    
                    {# Using explicit names #}
                    <ol>
                        {% for topping in topping_list %}
                            <li>{{ topping }} </li>
                        {% endfor %}
                    </ol>
                    
                    
                    1
                    2
                    3
                    4
                    5
                    6
                    7
                    8
                    9
                    10
                    11
                    12
                    13
                    14
                    15

                    # 使用 url 名字来代替硬编码的url

                    Bad exemple:
                    <a href="/flavors/">
                    
                    Right exemple:
                    <a href="{% url 'flavors_list' %}">
                    
                    1
                    2
                    3
                    4
                    5

                    # debug 的时候可以开启,页面详细错误

                    # settings/local.py
                    TEMPLATES = [{
                            'BACKEND': 'django.template.backends.django.DjangoTemplates',
                            'APP_DIRS': True,
                            'OPTIONS':
                            'string_if_invalid': 'INVALID EXPRESSION: %s'
                        },
                    ]
                    
                    1
                    2
                    3
                    4
                    5
                    6
                    7
                    8

                    # 错误模板的设置

                    在生产环境中,一定要设置错误页面,但不要过使页面复杂。

                    # 第十四章 模板的 tags 和 filters

                    # filter 什么时候使用

                    • 格式化模板中数据
                    • rest api 中数据的格式化

                    # 自定义 tags

                    尽量书写少的tags :

                    • tags 比较难调试
                    • 使代码不容易重用
                    • 性能消耗比较大

                    # 命名 tags 类库

                    tags.py

                    # 在 template 页面中加载 tags

                    {% extends "base.html" %}
                    {% load flavors_tags %}
                    
                    # Don't use this code!
                    # It's an evil anti-pattern!
                    from django import template
                    template.add_to_builtins(
                        "flavors.templatetags.flavors_tags"
                    )
                    
                    1
                    2
                    3
                    4
                    5
                    6
                    7
                    8
                    9

                    # 第十五章 Django 模板(DTL) 和 jinja2

                    # 不同之处

                    # 我们应该如何选择

                    # DTL 的优点

                    • django 的所有官方文档使用 DTL,便于理解。
                    • django + DTL 的组合更成熟。
                    • 大多数的django 三方包使用的是 DTL。
                    • 转化 DTL到jinja2需要大量的工作。

                    # jinjia2 的优点

                    • 在django中可以被单独使用。
                    • jinja2 的语法更接近 python的语法。
                    • jinja2 更明确,例如函数的调用带有括号。
                    • jinja2 有更少的限制,例如可以给一个filter传递无限个参数。而DTL 只能传一个。
                    • jinja2 渲染更快。

                    # 如何选择

                    • 新手建议使用 DTL
                    • 页面简单的使用 DTL ,复杂的使用 jinja2
                    • 一个项目中,我们可以2个都使用。一个作为主要的模板,另一个为辅。

                    # jinja2 部分使用举例

                    # CSRF

                    <div style="display:none">
                    <input type="hidden" name="csrfmiddlewaretoken" value="{{ csrf_token }}">
                    </div>
                    
                    1
                    2
                    3

                    # jinja2 无法使用 自定义 tags的

                    # jinja2 中使用 django-style 的 filter

                    # core/jinja2.py
                    from __future__ import absolute_import # Python 2 only
                    from django.contrib.staticfiles.storage import staticfiles_storage
                    from django.core.urlresolvers import reverse
                    from django.template import defaultfilters
                    
                    from jinja2 import Environment
                    def environment(**options):
                        env = Environment(**options)
                        env.globals.update({
                        'static': staticfiles_storage.url,
                        'url': reverse,
                        'dj': defaultfilters
                        })
                        return env
                    
                    
                    1
                    2
                    3
                    4
                    5
                    6
                    7
                    8
                    9
                    10
                    11
                    12
                    13
                    14
                    15
                    16
                    <table><tbody>
                    {% for purchase in purchase_list %}
                        <tr>
                        <a href="{{ url("purchase:detail", pk=purchase.pk) }}">
                            {{ purchase.title }}
                        </a>
                        </tr>
                        <tr>{{ dj.date(purchase.created, "SHORT_DATE_FORMAT") }}</tr>
                        <tr>{{ dj.floatformat(purchase.amount, 2) }}</tr>
                    {% endfor %}
                    </tbody></table>
                    
                    1
                    2
                    3
                    4
                    5
                    6
                    7
                    8
                    9
                    10
                    11

                    # 上下文 context 不能在 jinja2 中使用

                    我们可以自定义中间件

                    # advertisements/middleware.py
                    import random
                    from advertisements.models import Advertisement as Ad
                    
                    def AdvertisementMiddleware(object):
                        def process_request(request):
                            count = Advertisement.objects.filter(subject='ice-cream').count()
                            ads = Advertisement.objects.filter(subject='ice-cream')
                            # If necessary, add a context variable to the request object.
                            if not hasattr(request, 'context'):
                            request.context = {}
                            # Don't overwrite the context, instead we build on it.
                            request.context.update({'ad': ads[random.randrange(0, count)]})
                    
                    <!-- base.html -->
                    {% set ctx = request.context %}
                    ...
                    <div class="ice-cream-advertisement">
                        <a href="{{ ctx.ad.url }}">
                            <img src="ctx.ad.image.url" />
                        </a>
                    </div>
                    
                    1
                    2
                    3
                    4
                    5
                    6
                    7
                    8
                    9
                    10
                    11
                    12
                    13
                    14
                    15
                    16
                    17
                    18
                    19
                    20
                    21
                    22
                    #Django#Django最佳实践
                    上次更新: 2023/03/28, 16:27:19
                    最近更新
                    01
                    chromebox/chromebook 刷bios步骤
                    03-01
                    02
                    redis 集群介绍
                    11-28
                    03
                    go语法题二
                    10-09
                    更多文章>
                    Theme by Vdoing | Copyright © 2015-2024 DeanWu | 遵循CC 4.0 BY-SA版权协议
                    • 跟随系统
                    • 浅色模式
                    • 深色模式
                    • 阅读模式