flask-day4:自定义过滤器|模板中的宏|模板中的include(包含)|

自定义过滤器"response值|过滤器名称"

@app.template_filter(“times”)
app.py

from datetime import datetime

from flask import Flask,render_template

app = Flask(__name__)


@app.route('/')
def index():
    context = {
        "create_time": datetime(2020,4,13,10,2,40),    # response的值
        }
    return render_template("index.html",**context)

# print((datetime.now()-datetime(2020,4,13,10,2,40).)
print(datetime(2020,4,13,10,2,40))
now = datetime.now()
time1 = datetime(2020,4,13,10,2,40)
print((now-time1).total_seconds())

@app.template_filter("time_filter")   #过滤器
def handle_time(time):        #过滤器是一个函数
    if isinstance(time,datetime):
        now = datetime.now()
        timestamp = (now - time).total_seconds()
        if timestamp < 60:
            return "刚刚"
        elif timestamp>=60 and timestamp < 60*60:
            minutes = timestamp/60
            return "%s分钟前"% int(minutes)
        elif timestamp>=60*60  and  timestamp < 60*60*24:
            hours = timestamp/(60*60)
            return "%s小时前" % int(hours)
        elif timestamp >= 60*60*24 and timestamp <60*60*24*30:
            days = timestamp/(60*60*24)
            return "%s天前"%int(days)`
        else:
            return time.strftime("%Y-%m-%d %H:%M:%S")
    else:
        return time

if __name__ == '__main__':
    app.run()

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>这是一篇文章</h1>
<p>发表时间:{{ create_time | time_filter }}</p>   #time_filter是自定义过滤器
</body>
</html>

访问index.html,向服务器request.app.py返回create_time,index.html request此值并调用过滤器.

自动转义(模板中:{%autoescape false%})

转义的概念是,在模板渲染字符串的时候,字符串有可能包括一些非常危险的字符比如<>等,这些字符会破坏掉原来HTML标签的结构,更严重的可能会发生XSS跨域脚本攻击,因此如果碰到<>这些字符的时候,应该转义成HTML能正确表示这些字符的写法,比如>HTML中应该用&lt;来表示等。

但是Flask中默认没有开启全局自动转义,针对那些以.html.htm.xml.xhtml结尾的文件,如果采用render_template函数进行渲染的,则会开启自动转义。并且当用render_template_string函数的时候,会将所有的字符串进行转义后再渲染。而对于Jinja2默认没有开启全局自动转义,作者有自己的原因:

  1. 渲染到模板中的字符串并不是所有都是危险的,大部分还是没有问题的,如果开启自动转义,那么将会带来大量的不必要的开销。
  2. Jinja2很难获取当前的字符串是否已经被转义过了,因此如果开启自动转义,将对一些已经被转义过的字符串发生二次转义,在渲染后会破坏原来的字符串。

在没有开启自动转义的模式下(比如以.conf结尾的文件),对于一些不信任的字符串,可以通过{{ content_html|e }}或者是{{ content_html|escape }}的方式进行转义。在开启了自动转义的模式下,如果想关闭自动转义,可以通过{{ content_html|safe }}的方式关闭自动转义。而{%autoescape true/false%}...{%endautoescape%}可以将一段代码块放在中间,来关闭或开启自动转义,例如以下代码关闭了自动转义:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>这是一篇文章</h1>
<p>发表时间:{{ create_time | time_filter }}</p>
弹出代码位置:
{% autoescape false %}   # 取消转义
{{ beng }}
{% endautoescape %}

</body>
</html>
@app.route('/')
def index():
    context = {
        "create_time": datetime(2020,4,13,10,2,40),
        "beng":"<script>alert('hi')</script>"  #包含script,默认是被转义的
        }
    return render_template("index.html",**context)

有些html代码需要转义,如script代码,有时不需要转义,如加粗等.

宏macros和import宏

模板中的宏跟python中的函数类似,可以传递参数,但是不能有返回值,可以将一些经常用到的代码片段放到宏中,然后把一些不固定的值抽取出来当成一个变量,以下将用一个例子来进行解释,该例使用宏来创建3个不同的:

定义宏macros.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
{% macro  createInput(type,name="",value="")%}            # 定义宏
    <input type="{{ type }}",name="{{ name }}",value="{{ value }}">
{% endmacro %}
</body>
</html>

应用宏index.html:

{% import "macros.html" as macro%}   #导入宏
<!-- 或者:{% from "macros.html" import createInput as inp %}  -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<p>macros:</p>
<form action="" method="get">
用户:{{  macro.createInput(type="text",name="username",value="abc") }}  #创建第一个input
密码:{{ macro.createInput(type="password",name="password") }} #创建第二个表单
{{  macro.createInput(type="submit",name="submit",value="提交") }}  # 创建第三个表单
</form>
</body>
</html>

可见,宏是模板中的宏,一般是定义一个macros.html用于存放各种宏方法,再在各模板中导入该宏,使用该方法.

模板中的include

include可以将常用的网页部分(如head和foot)做成head.html和foot.html,在某一网页中包含它们即可.这是一个模板上用的,一般将head.html和foot.html放在templates目录下的common目录:
head.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
</head>
<body>
<nav class="navbar navbar-default">
  <div class="container-fluid">
    <!-- Brand and toggle get grouped for better mobile display -->
    <div class="navbar-header">
      <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
        <span class="sr-only">Toggle navigation</span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
      </button>
      <a class="navbar-brand" href="#">Brand</a>
    </div>

    <!-- Collect the nav links, forms, and other content for toggling -->
    <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
      <ul class="nav navbar-nav">
        <li class="active"><a href="#">Link <span class="sr-only">(current)</span></a></li>
        <li><a href="#">Link</a></li>
        <li class="dropdown">
          <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a>
          <ul class="dropdown-menu">
            <li><a href="#">Action</a></li>
            <li><a href="#">Another action</a></li>
            <li><a href="#">Something else here</a></li>
            <li role="separator" class="divider"></li>
            <li><a href="#">Separated link</a></li>
            <li role="separator" class="divider"></li>
            <li><a href="#">One more separated link</a></li>
          </ul>
        </li>
      </ul>
      <form class="navbar-form navbar-left">
        <div class="form-group">
          <input type="text" class="form-control" placeholder="Search">
        </div>
        <button type="submit" class="btn btn-default">Submit</button>
      </form>
      <ul class="nav navbar-nav navbar-right">
        <li><a href="#">Link</a></li>
        <li class="dropdown">
          <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a>
          <ul class="dropdown-menu">
            <li><a href="#">Action</a></li>
            <li><a href="#">Another action</a></li>
            <li><a href="#">Something else here</a></li>
            <li role="separator" class="divider"></li>
            <li><a href="#">Separated link</a></li>
          </ul>
        </li>
      </ul>
    </div><!-- /.navbar-collapse -->
  </div><!-- /.container-fluid -->
</nav>

</body>
</html>

foot.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
</head>
<body>
<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>

要引用的网页如include.html:

{%  include "common/head.html" %}   #包含head.html
<h1>这是中间内容</h1>
{%  include "common/foot.html" %}  #包含foot.html

include.html页面就会显示head.html+自己的内容+foot.html
可见include方法是使用在模板中的.

继承extends

继承是模板中的网页继承自某个base.html,base.html指定可以编辑的部分。
base.html(一般位于common目录下):

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>{% block title %}        #这是命名为title的block
这是一个基类网页
{% endblock %}</h1>
<p>base.html位于common目录下</p>   
<p>使用方法:{% block  fangfa%}  from base {% endblock %}</p> #这是命名为fangfa的block
</body>
</html>

page1.html(继承base.html):

{% extends "common/base.html" %}   #继承base.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
{% block title %}                 #在base.html的基础上修改title
    这是一个测试网页1
{% endblock %}
{% block fangfa %}                 #在base.html的基础上-
    <h1>这是测试网页的介绍方法</h1>         -增加的内容      
    {{  super() }}                        #base.html定义的内容

{% endblock %}
</body>
</html>

static目录

在flask目录中新建static目录,右键将其设为sources root在这里插入图片描述
开发网站时将js,css,images等静态资源放在此处。

使用时,在模板中用url_for调用即可,如=={{url_for(“static”,filename=“yellow-girl.jpg”)}}==

{% extends "common/base.html" %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
{% block title %}
    这是一个测试网页1
    <img src="{{ url_for("static",filename="yellow-girl.jpg")}}"> #图片是static目录下的yellow-girl.jpg
{% endblock %}
</body>
</html>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值