• flask框架 模板相关


    模板

    什么是模板引擎?

    实现视图的业务逻辑和返回给前端的页面逻辑分离的工具,我们称之为模板引擎。

    为什么要有模板引擎?

    如果没有模板引擎,直接把模板的html代码写在视图函数里面,会给程序员的日常开发带来多大的困扰,模板引擎帮我们分开了业务逻辑和页面逻辑,并且我们每一次修改一个大字符串会非常不方便,模板引擎还可以读取并执行模板中的特殊语法标记,并根据传入的数据将变量替换为实际值,然后返回给浏览器,这个过程我们称之为渲染。

    Flask中如何使用模板引擎?

    flask使用jinjia2作为框架的默认模板引擎,jinjia2是基于Python的模板引擎,功能比较类似以phpsmartyJ2eeFreemarkervelocityjinjia2除了设置变量,还允许我们在模板中添加if判断,执行for迭代,调用函数等,以各种方式控制模板的输出。并且jinja2不限制模板的格式为html,可以是任何格式的文本文件。

    模板引擎传参

    传参的时候要应用render_template(),利用render_template的第二个参数进行传参,该函数在定义的时候,第二个参数是可变长形参,所以在传值的时候我们可以传入多个关键字实参。

    我们定义的视图函数内部调用渲染模板:

    render_template('list.html',info=info,html="<h1>jsaon-gdx</h1>",html1=func1)
    

    源码接收关键字实参:

    def render_template(template_name_or_list, **context):
    

    注意:

    ​ render_template传参的时候以关键字实参进行传参。可以传多个,可以使用**将字典打散成关键字实参。

    def demo2():
        context_dict = {"name": "mark",
                   "age": "mark",
                   "sex": "girl",
                    "other_info":{"tel":1365,
                                   "qq":565656}}
    
        return render_template('index.html',**context_dict)
    
    <!--index.html-->
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>模板传参</title>
    </head>
    <body>
        {{name}}
        {{age}}
        {{sex}}
        {{other_info.tel}}
        {{other_info["qq"]}}
    </body>
    </html>
    

    模板加载静态文件

    在模板中加载静态文件的时候也要使用到url_for()函数,去寻找具体的静态文件资源。第一个参数是定位到static文件夹,filename参数定位到static文件夹内的具体资源。

    {{ url_for('static',filename='相对于static文件夹的路径') }}
    

    实例:

    项目目录:

    │  app.py
    │
    ├─static  # 文件夹
    │  ├─css  # 文件夹
    │  │      demo.css
    │  │
    │  ├─images  # 文件夹
    │  │      1.png
    │  │
    │  └─js  # 文件夹
    │          demo.js
    │
    ├─templates  # 文件夹
         index.html
    
    

    app.py

    ...
    
    @app.route('/')
    def hello_world():
        return render_template('index.html')
    ...
    

    index.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>静态文件加载</title>
        
        <link rel="stylesheet" href="{{ url_for('static',filename='css/demo.css') }}">
        <script src="{{ url_for('static',filename='js/demo.js') }}"></script>
        
    </head>
    <body>
        <img src="{{ url_for('static',filename='images/1.png') }}">
    </body>
    </html>
    

    demo.css

    body{
        background: red;
    }
    

    demo.js

    alert('hello world')
    

    模板的继承

    jinja2的模板的继承可以把一些公共的代码定义到一个基模板中,以后所有的子模板直接继承基模板,在子模板被渲染是会自动包含继承基模板的内容,通过模板的继承可以避免在多个模板中编写重复代码。

    具体实现:

    在基模板中定义一些公共的代码,子模板会继承这些公共的代码,但是子模板需要根据自己的需求去实现不同的代码,这个时候就需要在基模板中提供一些接口,以便子模板实现自己的业务需求。

    1.基本写法

    在基/父模板中定义接口(block)

    {% block main %} {# main是自定义的变量名 #}
    
    {% endblock %}
    

    在子模板中继承父模板,并且重写接口(block)

    {% extends 'base.html' %} {# extends 后面跟的参数是导入的基模板相对于templates的路径 #}
    {% block main %}
        
    {% endblock %}
    

    2.子模板中调用父模板代码block中的代码

    基模板中

    {% block main %}
    <p>父模板中main中原有的内容</p>
    
    {% endblock %}
    

    子模板中:

    {% block main %}
        {{ super() }}   {# 保留基模板中本块的代码 #}
        <p>子模板中重写main的内容 </p>
    {% endblock %}
    

    3.在子模板中调用其他block中的代码:

    子模板中:

    {% block main %}
        {{ self.demo() }} {# self.其他block名字 #}
        <p>子模板中重写main的内容 </p>
    {% endblock %}
    

    4.子模板中的想定义自己的代码只能放到block中,否则无效

    base.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>父模板</title>
        <link rel="stylesheet" href="{{ url_for('static',filename='css/bootstrap.css') }}">
    </head>
    <body>
        <form class="navbar-form navbar-left" role="search">
          <div class="form-group">
            <input type="text" class="form-control" placeholder="Search">
          </div>
          <button type="submit" class="btn btn-default">Submit</button>
        </form>
        <div style=" visibility:hidden;display:block;font-size:0;clear:both;
                height:50px"></div>
    
    
        {% block main %}
            <p>父模板中main中原有的内容</p>
    
        {% endblock %}
       <br>
       <br>
       <br>
        {% block demo %}
            <p>demo中原有的内容</p>
        {% endblock %}
    
    
    <div style=" visibility:hidden;display:block;font-size:0;clear:both;
                height:0"></div>
    <nav aria-label="Page navigation">
      <ul class="pagination">
        <li>
          <a href="#" aria-label="Previous">
            <span aria-hidden="true">&laquo;</span>
          </a>
        </li>
        <li><a href="#">1</a></li>
        <li><a href="#">2</a></li>
        <li><a href="#">3</a></li>
        <li><a href="#">4</a></li>
        <li><a href="#">5</a></li>
        <li>
          <a href="#" aria-label="Next">
            <span aria-hidden="true">&raquo;</span>
          </a>
        </li>
      </ul>
    </nav>
    
    </body>
    </html>
    

    detail.html

    {% extends 'base.html' %}
    {% block demo %}
        <p>子模板中重写demo的内容</p>
    {% endblock %}
    {% block main %}
        {{ super() }}   {# 保留基模板中本block的代码 #}
        {{ self.demo() }} {# 调用demo block的代码 #}
        <p>子模板中重写main的内容 </p>
    {% endblock %}
    

    app.py 注意:app.config.update(TEMPLATE_AUTO_RELOAD=True)语句用于每次都重新加载模板文件

    from flask import Flask, render_template
    
    app = Flask(__name__)
    app.config.update(TEMPLATES_AUTO_RELOAD=True)
    
    @app.route('/')
    def hello_world():
        return render_template('base.html')
    
    @app.route('/demo/')
    def demo():
        return render_template('detail.html')
    
    
    if __name__ == '__main__':
        app.run()
    

    子模板运行效果

    模板小案例

    flask框架前端的反向解析用的也是后端的url_for("函数名"),<a href="{{url_for('sb',nid=k)}}">查看详细</a>可以解析出路由和浏览器传来的动态路由(nid=k),点击a标签跳转路由。
    
     Markup:flask中后端过滤器,表明后端Markup传来的html是安全的,可以渲染。
     
    {{html|safe}} :后端没有使用Markup过滤器表明html是安全的,前端可以使用模板过滤器,渲染html,类似Django的过滤器。
    
    后端传的变量是一个函数名(html1=func1)给前端,前端拿到函数名加括号使用模板语法就可以调用后端写的函数,还可以在模板语法中给该函数传参,例:{{html1("-DSB","-SB")}}。Django中的前端使用函数或类进行渲染是不需要加括号的,内部会自动加括号调用函数或实例化一个对象。
    
    
    render_template('box/login.html')的路径是template文件夹的相对路径
    
    
    from flask import Flask,render_template,request,redirect,session,url_for,Markup
    app = Flask(__name__)
    app.debug = True
    app.secret_key = 'sdfsdfsdfsdf'
    
    USERS = {
        1:{'name':'张三','age':18,'gender':'男','text':"道路千万条"},
        2:{'name':'李四','age':28,'gender':'男','text':"安全第一条"},
        3:{'name':'王五','age':18,'gender':'女','text':"行车不规范"},
    }
    def func1(st,st1):
        return Markup(f"<h1>jsaon-gdx{st}{st1}</h1>") # flask中后端过滤器,表明后端Markup传来的html是安全的,可以渲染。
    
    @app.route('/list',methods=['GET'])
    def list():
        info=USERS
    
        return render_template('list.html',info=info,html="<h1>jsaon-gdx</h1>",html1=func1)
    @app.route('/detail/<int:nid>',methods=['GET'],endpoint="sb")
    def detail(nid):
    
        return "ok"
    
    if __name__ == '__main__':
        app.run()
    
    <!--list.html-->
    
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    
    </head>
    <body>
    {% for k,v in info.items() %}
            <tr>
                <td>{{k}}</td>
                <td>{{v.name}}</td>
                <td>{{v['name']}}</td>
                <td>{{v.get('name')}}</td>
                <td><a href="{{url_for('sb',nid=k)}}">查看详细</a></td>
            </tr>
    {% endfor %}
    {{html|safe}} 
    {{html1("-DSB","-SB")}}
    
    </body>
    </html>
    
    <!--index.html-->
    
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    
    </head>
    <body>
    {{sb(1,2)}}
    {{1|db(2,3)}}
    </body>
    </html>
    
  • 相关阅读:
    【BZOJ2525】[Poi2011]Dynamite 二分+树形DP
    【BZOJ2560】串珠子 状压DP+容斥
    【BZOJ2726】[SDOI2012]任务安排 斜率优化+cdq分治
    [NOIP2017]宝藏 状压DP
    [NOIP2017]逛公园 最短路+拓扑排序+DP
    [NOIP2017]列队 离线+SBT
    【CF628D】Magic Numbers 数位DP
    【BZOJ2791】[Poi2012]Rendezvous 倍增
    sql 通过游标 拆分xml结构
    sql字符转换函数大全
  • 原文地址:https://www.cnblogs.com/zhangchaocoming/p/12348601.html
Copyright © 2020-2023  润新知