Flask学习总结笔记(4)-- Jinja2模板引擎之二

Jinja2模板引擎官方文档详细介绍了其中的API函数、沙箱、模板设计文档等,这里主要就一些常用的知识点进行总结。

0x01 模板基础

常见的几种模板语句如下:

{%...%}     #运行Jinja2的语句;
{{…}}       #在页面中打印Jinja2运行的结果
{#...#}     #注释

看下面的例子:

(1)views.py

from flask import render_template

@app.route('/index')
def index():
    return render_template('index1.html',
                           name='kikay',
                           age=20)

(2)templates文件夹下新建模板index1.html:


<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Testtitle>
head>
<body>
<p>测试p>
<p>直接输出姓名:{{name}}p>
{#这是注释:判断是否存在age#}
{%if age%}
<p>年龄:{{age}}p>
{%else%}
<p>不存在年龄p>
{%endif%}
body>
html>

输出效果:

Flask学习总结笔记(4)-- Jinja2模板引擎之二_第1张图片

如果想输入原始的Jinja2语句,而不是作为特殊字符进行解析,可以包含在{%raw%}…{%%endraw}中:
views.py

@app.route('/raw')
def raw():
    return render_template('raw.html',name='kikay')

raw.html


<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Rawtitle>
head>
<body>
<div>
    <p>姓名:{{name}}p>
    {%raw%}
    <p>转义姓名:{{name}}p>
    {%endraw%}
div>
body>
html>

效果如下:

Flask学习总结笔记(4)-- Jinja2模板引擎之二_第2张图片

上面的例子都需要调用render_template('*.html',var_key=***)来渲染模板。其中的函数render_template是把Jinja2模板引擎集成到程序中。Jinja2 能识别所有类型的变量,甚至是一些复杂的类型,例如列表、字典和对象。

0x02 控制语句

添加一些控制语句,index2.html如下:


<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>{{title}}title>
head>
<body>
<div>
    {%if author%}
    <h1>Hello,{{author}}h1>
    {%else%}
    <h1>Nobodyh1>
    {%endif%}
div>
body>
html>

views.py:

@app.route('/index2')
def index2():
    author='kikay'
    return render_template('index2.html',
                           author=author)

输出:

Flask学习总结笔记(4)-- Jinja2模板引擎之二_第3张图片

注释掉author:

@app.route('/index2')
def index2():
    author='kikay'
    return render_template('index2.html')
                           #author=author)

效果如下:

Flask学习总结笔记(4)-- Jinja2模板引擎之二_第4张图片

当参数不存在时,Jinja2模板在渲染时直接忽略掉。更复杂一些,现在还要输出作者好友的列表。

index3.html:


<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Firendstitle>
head>
<body>
<div>
    <h1>作者:{{author.name}}h1>
    <table>
        <thread>
            <th>姓名th>
            <th>年龄th>
        thread>
        {%for f in author.friends%}
        <tr>
            <td>{{f.name}}td>
            <td>{{f.age}}td>
        tr>
        {%endfor%}
    table>

div>
body>
html>

views.py:

@app.route('/index3')
def index3():
    author={
        'name':'kikay',
        'age':20,
        'friends':[
            {'name':'Andy','age':60},
            {'name':'Tom','age':29},
            {'name':u'小花','age':18}
        ]
    }
    return render_template('index3.html',
                           author=author)

效果如下:

Flask学习总结笔记(4)-- Jinja2模板引擎之二_第5张图片

这里需要指出的是,输出带有中文时,注意编码的问题。类似于Python中函数的定义,Jinja2模板引擎中的macro关键字可以看成是一个函数的定义:

{%macro showinfo(info)%}
这是{{info}}!!!<br />
{%endmacro%}
{%for info in infos%}
{{showinfo(info)}}
{%endfor%}

0x03 模板继承

随着应用的拓展,我们可能在多个页面中使用了相同的HTML代码,并且需要每一个页面都同步,和其他模板引擎一样,Jinja2也支持模板继承。我们在templates下新建一个layout_base.html文件,内容如下:


<html lang="en">
<head>
    <meta charset="UTF-8">
    {%if title%}
    <title>{{title}}title>
    {%else%}
    <title>No titletitle>
    {%endif%}
    
    {%block script%}
    <script src="test.js">script>
    {%endblock%}
head>
<body>
<div>
    {%block t1%}{%endblock%}
    <p>----------模板分隔符------------p>
    {%block t2%}{%endblock%}
div>
body>
html>

里面有3个block标签,这是为继承该模板的html模板替换使用的。新建index4.html继承layout_base.html:

{%extends 'layout_base.html'%}
{%block script%}
{{super()}}
<script src="test2.js">script>
{%endblock%}

{%block t1%}
{%if author%}
<h1>Hello,{{author.name}}h1>
{%else%}
<h1>Nobodyh1>
{%endif%}
{%endblock%}

{%block t2%}
<table>
    <thread>
        <th>姓名th>
        <th>年龄th>
    thread>
    {%for f in author.friends%}
    <tr>
        <td>{{f.name}}td>
        <td>{{f.age}}td>
    tr>
    {%endfor%}
table>
{%endblock%}

效果如下:

Flask学习总结笔记(4)-- Jinja2模板引擎之二_第6张图片

extends指明该模板是从哪个模板继承而来的。上面例子中的{{super()}},因为模板中其中包含的内容不是空的,所以需要用{{super()}}来获取原来的内容。如果一个html中包含1个以上的extends标签就会报错,即最多继承于1个模板。

0x04 模板设计

Flask集成了Bootstrap包,可以使用Flask-Bootstrap来渲染模板,首先需要安装(利用pip):

pip install flask-bootstrap

具体过程参见以前的博客(Flask学习总结笔记(1)– 环境配置)。

__init__.py中初始化Flask-Bootstrap:

from flask.ext.bootstrap import Bootstrap

修改后的完整__init__.py如下:

#!flask/bin/env python
#coding:utf-8

__author__ = 'kikay'

from flask import Flask
from flask.ext.bootstrap import Bootstrap

#定义app对象
app=Flask(__name__)
#定义Bootstrap对象
bootstrap=Bootstrap(app)

from app import views

完成Flask-Bootstrap初始化后,就可以在程序中使用一个包含全部Bootstrap文件的基模板。这个模板利用Jinja2的模板继承机制,让程序扩展一个具有基本页面结构的基模板,其中就有用来引入 Bootstrap 的元素。(官方教程),关于Bootstrap的内容可以参看我的博客(Bootstrap学习总结笔记)。

下面是实现一个导航样式的例子:

bootstrap.html


{%extends 'bootstrap/base.html'%}


{%block html_attribs%}lang="zh-cn"{%endblock%}


{%block metas%}
    {{super()}}
    <meta charset="UTF-8">
{%endblock%}


{%block styles%}
    {{super()}}
    <link rel="stylesheet" href="{{url_for('.static',filename='css/block.css')}}">
{%endblock%}

{%block scripts%}
    {{super()}}
    <script src="{{url_for('.static',filename='js/block.js')}}">script>
{%endblock%}


{%block title%}Flask-Bootstrap{%endblock%}


{%block navbar%}
<div class="container">
    <nav class="navbar navbar-inverse">
        <div class="navbar-header">
            <button type="button" class="btn btn-default navbar-toggle" data-toggle="collapse" data-target="#navbar">
                <span class="sr-only">Toggle navigationspan>
                <span class="icon-bar">span>
                <span class="icon-bar">span>
                <span class="icon-bar">span>
            button>
            <a href="#" class="navbar-brand">网站标题a>
        div>
        <div class="collapse navbar-collapse" id="navbar">
            <ul class="nav navbar-nav">
                <li class="active"><a href="#">首 页a>li>
                <li><a href="#">新闻a>li>
                <li class="dropdown">
                    <a href="#" class="dropdown-toggle" data-toggle="dropdown">
                        下拉菜单
                        <span class="caret">span>
                    a>
                    <ul class="dropdown-menu">
                        <li><a href="#">菜单1a>li>
                        <li><a href="#">菜单2a>li>
                        <li><a href="#">菜单3a>li>
                    ul>
                li>
            ul>
            <form class="nav navbar-form navbar-right">
                <div class="form-group">
                    <input type="text" class="form-control" placeholder="用户名">
                div>
                <div class="form-group">
                    <input type="password" class="form-control" placeholder="密码">
                div>
                <div class="form-group">
                    <button type="submit" class="btn btn-primary form-control">提 交button>
                div>
            form>
        div>
    nav>
div>
{%endblock%}


{%block content%}
<div class="container">
    <div class="page-header">
        {%if author%}
        <h1>Hello,{{author.name}}h1>
        {%else%}
        <h1>Nobodyh1>
        {%endif%}
    div>
    <div class="col-center-block">
        
        {%if author.friends%}
        <table class="table table-bordered table-striped table-hover table-condensed">
            <thead class="alert-danger">
                <th>姓名th>
                <th>年龄th>
            thead>
            {%for f in author.friends%}
            <tr class="alert-success">
                <td>{{f.name}}td>
                <td>{{f.age}}td>
            tr>
            {%endfor%}
        table>
        {%endif%}
    div>
div>
<script>
script>
{%endblock%}

views.py:

@app.route('/bootstrap')
def bootstrap():
    author={
        'name':'kikay',
        'age':20,
        'friends':[
            {'name':'Andy','age':60},
            {'name':'Tom','age':29},
            {'name':u'小花','age':18}
        ]
    }
    return render_template('bootstrap.html',
                           author=author,
                           title='Bootstrap')

效果如下:

Flask学习总结笔记(4)-- Jinja2模板引擎之二_第7张图片

看下源代码,可以更好理解这种渲染的效果。



<htmllang="zh-cn">
  <head>
    <title>Flask-Bootstraptitle>

    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta charset="UTF-8">


    
    <link href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
    <link rel="stylesheet" href="/static/css/block.css">

  head>
  <body>

<div class="container">
    <nav class="navbar navbar-inverse">
        <div class="navbar-header">
            <button type="button" class="btn btn-default navbar-toggle" data-toggle="collapse" data-target="#navbar">
                <span class="sr-only">Toggle navigationspan>
                <span class="icon-bar">span>
                <span class="icon-bar">span>
                <span class="icon-bar">span>
            button>
            <a href="#" class="navbar-brand">网站标题a>
        div>
        <div class="collapse navbar-collapse" id="navbar">
            <ul class="nav navbar-nav">
                <li class="active"><a href="#">首 页a>li>
                <li><a href="#">新闻a>li>
                <li class="dropdown">
                    <a href="#" class="dropdown-toggle" data-toggle="dropdown">
                        下拉菜单
                        <span class="caret">span>
                    a>
                    <ul class="dropdown-menu">
                        <li><a href="#">菜单1a>li>
                        <li><a href="#">菜单2a>li>
                        <li><a href="#">菜单3a>li>
                    ul>
                li>
            ul>
            <form class="nav navbar-form navbar-right">
                <div class="form-group">
                    <input type="text" class="form-control" placeholder="用户名">
                div>
                <div class="form-group">
                    <input type="password" class="form-control" placeholder="密码">
                div>
                <div class="form-group">
                    <button type="submit" class="btn btn-primary form-control">提 交button>
                div>
            form>
        div>
    nav>
div>


<div class="container">
    <div class="page-header">

        <h1>Hello,kikayh1>

    div>
    <div class="col-center-block">
        

        <table class="table table-bordered table-striped table-hover table-condensed">
            <thead class="alert-danger">
                <th>姓名th>
                <th>年龄th>
            thead>

            <tr class="alert-success">
                <td>Andytd>
                <td>60td>
            tr>

            <tr class="alert-success">
                <td>Tomtd>
                <td>29td>
            tr>

            <tr class="alert-success">
                <td>小花td>
                <td>18td>
            tr>

        table>

    div>
div>
<script>
script>




    <script src="//cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js">script>
    <script src="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.min.js">script>
    <script src="/static/js/block.js">script>

  body>
html>

在Flask-Bootstrap中,支持的block样式如下表:

Flask学习总结笔记(4)-- Jinja2模板引擎之二_第8张图片

这里不再一一介绍,在实际应用中可以自己体会。另外上面用到了url_for函数做路由的映射,具体使用可以参见我前面的博客(Flask学习总结笔记(2)– Hello world程序)中关于构造Url的内容。这里引入了js和css文件,对应的文件结构如下:

Flask学习总结笔记(4)-- Jinja2模板引擎之二_第9张图片

关于Flask-Jinja2模板引擎的使用问题就讲到这里,以后在实际使用过程中,再慢慢总结与领会。

你可能感兴趣的:(Flask)