1. 程式人生 > >自定義模板語言整合

自定義模板語言整合

routes bing ret custom mod url mar == hand

  這篇文章主要對比一下兩大框架Tornado和Django自定義模塊語言,以及對Tornado的自定義模塊語言進行一個分離整合

  首先我們先看一下在Tornado裏,我怎麽實現的自定義模板語言

  • 第一步,創建UIMethods.py文件,寫入自定義方法(第一參數一定為self),創建UIModules.py文件,定義類(必須繼承Tornado一個導入類UIModule,通過重寫render方法實現)
  • 第二步,註冊到settings裏
  • 第三步,在模板語言裏調用 {{ 函數方法 }} {% module 類名(參數) %}
技術分享圖片
def tab(self):
    return UIMethod
UIMethods 技術分享圖片
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from tornado.web import UIModule
from tornado import escape
 
class custom(UIModule):
 
    def render(self, *args, **kwargs):
        return escape.xhtml_escape(<h1>wupeiqi</h1>)
        #return escape.xhtml_escape(‘<h1>wupeiqi</h1>‘)
UIModules
#! /usr/bin/env python
# -*- coding:utf-8 -*-
__author__ = "laoliu"

import tornado.ioloop
import tornado.web
from UIMethods import Method1 as mt1
from UIMethods import UIMethod2 as mt2


class MainHandler(tornado.web.RequestHandler):
    def get(self):
        self.render("hello.html")

settings = {
    ‘template_path‘: ‘views‘,        # html文件
    ‘static_path‘: ‘statics‘,        # 靜態文件(css,js,img)
    ‘static_url_prefix‘: ‘/statics/‘,# 靜態文件前綴
    ‘ui_methods‘: [mt1,mt2],              # 自定義UIMethod函數
    # ‘ui_modules‘: md,              # 自定義UIModule類
}

application = tornado.web.Application([
    (r"/index", MainHandler),  #localhost:9999/index
],**settings)



if __name__ == "__main__":
    application.listen(9999)
    tornado.ioloop.IOLoop.instance().start()
技術分享圖片
<body>
    <h1>hello</h1>
    {% module custom(123) %}
    {{ tab() }}
</body>
前端

  上述過程已經實現了在Tornado中的自定義模板語言,但是上述配置都還寫在啟動文件裏,沒有做到有效的分離,而且上面就光註冊到settings裏這一步,就要操作兩次,一個導入模塊,一個就是在settings裏寫入模塊名,能更簡潔一點呢?答案是有的

  我們是不是可以在配置文件裏為UIMethods和UIModules定義兩個組,組元素為要導入的文件路徑,然後在啟動程序文件裏只需要循環這兩個組,__import__導入就可以了

  • 在公共組件創建兩個文件夾,分別存放UIMethod模塊和UIModule模塊

技術分享圖片

  • 在配置文件中,定義兩個元組,分別存放要導入的模塊
ui_method = (
    ‘Infrastructure.UIMethods.Null‘,
)

ui_module = (
    ‘Infrastructure.UIModules.Null‘,
)

settings = {
    ‘template_path‘: ‘Views‘,
    ‘static_path‘: ‘Statics‘,
    ‘static_url_prefix‘: ‘/Statics/‘,
}
  • 在程序啟動文件,寫入加載自定義方法
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import tornado.ioloop
import tornado.web
import Config


def load_ui_module(settings):
    module_list = []
    for path in Config.ui_method:
        m = __import__(path, fromlist=True)
        module_list.append(m)
    settings[‘ui_modules‘] = module_list


def load_ui_method(settings):
    method_list = []
    for path in Config.ui_method:
        m = __import__(path, fromlist=True)
        method_list.append(m)
    settings[‘ui_methods‘] = method_list


def load_routes(app):
    for route in Config.routes:
        host_pattern = route[‘host_pattern‘]
        route_path = route[‘route_path‘]
        route_name = route[‘route_name‘]

        m = __import__(route_path, fromlist=True)
        pattern_list = getattr(m, route_name)

        app.add_handlers(host_pattern, pattern_list)


# def load_hook():
#     pass


def start():

    settings = {}

    load_ui_method(settings)
    load_ui_module(settings)

    settings.update(Config.settings)

    application = tornado.web.Application([
        #(r"/index", home.IndexHandler),
    ], **settings)

    load_routes(application)

    # load_hook()
    # print(‘http://127.0.0.1:8888‘)

    application.listen(8888)
    tornado.ioloop.IOLoop.instance().start()

if __name__ == "__main__":
    start()

  上面就達到我剛才說的那兩個目的了,只要寫好自定義方法,在配置文件裏配置一下路徑即可

  說了Tornado,那我們看下Django,對於這個大而全的框架,自定義模板語言在操作上限定非常死,必須按照它們的規則取創建使用

  註:操作前,必須確保你註冊了app

  • 第一步,在app中創建templatetags文件夾,並創建xx.py文件放在templatetags文件夾下,在xx.py文件定義HTML調用的方法

#xx.py
from django import template from django.utils.safestring import mark_safe from django.template.base import resolve_variable,Node,TemplateSyntaxError register = template.Library() @register.simple_tag def my_simple_time(v1,v2,v3): return v1+v2+v3 @register.simple_tag def my_input(id,arg): result = "<input type=‘text‘ id=‘%s‘ class=‘%s‘/>"%(id,arg,) return mark_safe(result)

  • 在需要進行渲染模板裏調用,首選要在模板文件頭部加載自定義方法文件{% load xx %},然後再調用函數 {% 函數名 參數 %}
{% load xx %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .hide{
            display:none;
        }
    </style>
</head>
<body>
    <h1>simple_tag</h1>
    {% my_input 123 ‘hide‘ %}
    <input type="button" onclick="show();"/>
    {% my_simple_time 1 2 3 %}
<script>
    function show(){
        var inp = document.getElementById(‘123‘);
        inp.classList.remove(‘hide‘);
    }
</script>
</body>
</html>

  除了自定義simple_tag之外,還可以自定義filter

#xx.py
from django import template
from django.utils.safestring import mark_safe
from django.template.base import resolve_variable,Node,TemplateSyntaxError
 
 
register = template.Library()
 
@register.filter
def detail(value,arg):
    allcount,remainder = arg.split(‘,‘)
    allcount = int(allcount)
    remainder = int(remainder)
    if value % allcount == remainder:
        return True
    return False
 
@register.filter
def func(val1,val2):
    if val1 + val2 == 2:
        return True
    return False

{% load xx %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>filter</h1>
    <div>
{#        {% if 1|func:1 %}#}
{#            <h1>bingo</h1>#}
{#        {% endif %}#}
 
        {% for item in detail_list %}
            {% if forloop.counter|detail:"4,0" %}
                <div>
                    <p>{{ item.name }}</p>
                </div>
            {% endif %}
        {% endfor %}
    </div>
<script>
 
</script>
</body>
</html>

  我們發現他們在定義時,裝飾器是不同的,另外還有以下幾點不同:

兩種自定義方式對比

  • 參數:sample_tag---任意參數,filter---只能兩個
  • 執行方式:sample_tag---{% 函數名:參數1 參數2 ... %},filter---{{ 參數一|函數名:參數二 }}
  • 支持條件if:sample_tag---不支持,filter---支持

自定義模板語言整合