8.odoo入门——jinja2入门(一)

来源:互联网 发布:新部落冲突4级地震数据 编辑:程序博客网 时间:2024/05/21 09:06

实习第8天:

早上开始学习jinja:

在odoo10/ws_training/controllers/main.py作为每个前端页面与后台交互的支点,有许多个通过以下方式,例如:

@http.route('/ws_training/signin', type='http', auth='public', csrf=False)def signin(self, **kwargs):

这样的形式路由的函数

那么具体的前端后台交互式如何实现的呢。

关注到main.py中的代码结构:

BASE_DIR = os.path.dirname(os.path.dirname(__file__))#参考:  http://blog.csdn.net/u011760056/article/details/46969883#BASE_DIR = "/Users/liuwanli/odoo10/wens_app/ws_training"templateLoader = FileSystemLoader(searchpath=BASE_DIR + "/templates")#在"/Users/liuwanli/odoo10/wens_app/ws_training/templates" 中加载文件env = Environment(loader=templateLoader)class MainController(http.Controller):def … #定义各种函数def …...

先看到类的外部定义, 文件系统的结构我们可以先不管,看到这个Environment对象,查看源码,在

/library/Python/2.7/site-packages/jinja2/environment.py中,源码结构复杂,先看到基本结构是:

def...def…def…class  Environment(object):#构造函数:   def __init__(self,                 block_start_string=BLOCK_START_STRING,                 block_end_string=BLOCK_END_STRING,                 variable_start_string=VARIABLE_START_STRING,                 variable_end_string=VARIABLE_END_STRING,                 comment_start_string=COMMENT_START_STRING,                 comment_end_string=COMMENT_END_STRING,                 line_statement_prefix=LINE_STATEMENT_PREFIX,                 line_comment_prefix=LINE_COMMENT_PREFIX,                 trim_blocks=TRIM_BLOCKS,                 lstrip_blocks=LSTRIP_BLOCKS,                 newline_sequence=NEWLINE_SEQUENCE,                 keep_trailing_newline=KEEP_TRAILING_NEWLINE,                 extensions=(),                 optimized=True,                 undefined=Undefined,                 finalize=None,                 autoescape=False,                 loader=None,                 cache_size=400,                 auto_reload=True,                 bytecode_cache=None,                 enable_async=False):        # !!Important notice!!        #   The constructor accepts quite a few arguments that should be        #   passed by keyword rather than position.  However it's important to        #   not change the order of arguments because it's used at least        #   internally in those cases:        #       -   spontaneous environments (i18n extension and Template)        #       -   unittests        #   If parameter changes are required only add parameters at the end        #   and don't change the arguments (or the defaults!) of the arguments        #   existing already.        # lexer / parser information        self.block_start_string = block_start_string        self.block_end_string = block_end_string        self.variable_start_string = variable_start_string        self.variable_end_string = variable_end_string        self.comment_start_string = comment_start_string        self.comment_end_string = comment_end_string        self.line_statement_prefix = line_statement_prefix        self.line_comment_prefix = line_comment_prefix        self.trim_blocks = trim_blocks        self.lstrip_blocks = lstrip_blocks        self.newline_sequence = newline_sequence        self.keep_trailing_newline = keep_trailing_newline        # runtime information        self.undefined = undefined        self.optimized = optimized        self.finalize = finalize        self.autoescape = autoescape        # defaults        self.filters = DEFAULT_FILTERS.copy()        self.tests = DEFAULT_TESTS.copy()        self.globals = DEFAULT_NAMESPACE.copy()        # set the loader provided        self.loader = loader        self.cache = create_cache(cache_size)        self.bytecode_cache = bytecode_cache        self.auto_reload = auto_reload        # configurable policies        self.policies = DEFAULT_POLICIES.copy()        # load extensions        self.extensions = load_extensions(self, extensions)        self.enable_async = enable_async        self.is_async = self.enable_async and have_async_gen        _environment_sanity_check(self)

上述代码生成了一个含loader模板的environment对象,再看到在类MainController中的前后台交互的函数中,最后两行往往是:

template = env.get_template("index.html")#加载一个模板: template = env.get_template(‘mytemplate.txt’), 使用env的模板环境加载名为#mytemplate.txt的模板文件.return template.render(data=datalist) #datalist是待传入数据,比如列表#渲染一个模板: template.render(name = ‘Jack’), 渲染模板template, 传入了模板参数name值为Jack

以上解析可以参考:

http://wsql.iteye.com/blog/1710859

http://docs.pythontab.com/jinja/jinja2/api.html (这个更好)

查看在environment.py下的Environment类下的get_template函数源码:

@internalcode    def get_template(self, name, parent=None, globals=None):        """Load a template from the loader.  If a loader is configured this        method ask the loader for the template and returns a :class:`Template`.        If the `parent` parameter is not `None`, :meth:`join_path` is called        to get the real template name before loading.        The `globals` parameter can be used to provide template wide globals.        These variables are available in the context at render time.        If the template does not exist a :exc:`TemplateNotFound` exception is        raised.        .. versionchanged:: 2.4           If `name` is a :class:`Template` object it is returned from the           function unchanged.        """        if isinstance(name, Template):            return name        if parent is not None:            name = self.join_path(name, parent)        return self._load_template(name, self.make_globals(globals))

恕我不能继续往下挖_load_template()函数了,这可能有很多层我还不了解的函数调用。

看到最后的核心,发送信息的函数render(),查看源码:

def render(self, *args, **kwargs):        """This method accepts the same arguments as the `dict` constructor:        A dict, a dict subclass or some keyword arguments.  If no arguments        are given the context will be empty.  These two calls do the same::            template.render(knights='that say nih')            template.render({'knights': 'that say nih'})        This will return the rendered template as unicode string.        """        vars = dict(*args, **kwargs)        try:            return concat(self.root_render_func(self.new_context(vars)))        except Exception:            exc_info = sys.exc_info()        return self.environment.handle_exception(exc_info, True)

可以看到,最终调用了

concat(self.root_render_func(self.new_context(vars)))

问题来了,又有3份源代码要看- - 

看到Environment类中的new_context源码:

    def new_context(self, vars=None, shared=False, locals=None):        """Create a new :class:`Context` for this template.  The vars        provided will be passed to the template.  Per default the globals        are added to the context.  If shared is set to `True` the data        is passed as it to the context without adding the globals.        `locals` can be a dict of local variables for internal usage.        """        return new_context(self.environment, self.name, self.blocks,                           vars, shared, self.globals, locals)

我这里好困,我要暂时放弃了- - 


原创粉丝点击