FLASK学习杂记(三)Flask模板

FLASK学习杂记(三)Flask模板

  • 一、Flask模板使用
    • 1.render_template()
    • 2.静态文件
    • 3.修改模板位置
  • 二、模板传参
    • 1.关键字传参
    • 2.封装字典传参
    • 3.**字典传参
    • 4.列表、元组、字典取用
  • 三、模板基础
    • 1.Jinja分隔符配置
    • 2.模板过滤器
      • 内置过滤器
      • 自定义过滤器
    • 3.结构控制
      • for循环
      • 条件语句
      • 块和模板继承
      • set
    • 4.Jinjia表达式

一、Flask模板使用

函数返回一段前端代码,会被flask自动解析,在前端中展示。

@app.route('/index')
def index():
    return '
请输入:
'

FLASK学习杂记(三)Flask模板_第1张图片
但直接返回html代码,不利于前后端分离,flask为此提供了Jinja2模板引擎,可以通过render_template()方法渲染模板,再返回给前端。

1.render_template()

写一个简单的html文件


<html lang="en">
	<head>
	    <meta charset="UTF-8">
	    <title>indextitle>
	head>
	<body>
		<h6>请输入:h6>
		<input name="inp">
	body>
html>

用render_template()渲染,flask会在templates文件夹内找到要渲染的html文件。

from flask import render_template

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

FLASK学习杂记(三)Flask模板_第2张图片

FLASK学习杂记(三)Flask模板_第3张图片

2.静态文件

在前端开发过程中,也需要css、js 静态文件,flask提供了一个static的文件夹,用于存储相关静态文件。
在static问价夹下新建一个css文件夹用于存储css文件,同理也可在此新建一个js文件夹,用于存储js文件。
FLASK学习杂记(三)Flask模板_第4张图片
这里可以用到url_for()来获取文件地址


<html lang="en">
	<head>
	    <meta charset="UTF-8">
	    <title>indextitle>
	    <link rel="stylesheet" href="{
      { url_for('static',filename='css/index.css') }}">
	head>
	<body>
		<h6>请输入:h6>
		<input name="inp">
	body>
html>

css修改h6标签颜色

h6{
     
    color: aquamarine;
}

FLASK学习杂记(三)Flask模板_第5张图片
如果想修改静态文件默认位置,可以在flask初始化时候设置static_folder

from flask import Flask
app = Flask(__name__,static_folder='staticfiles')

3.修改模板位置

如果想要自定义模板存放位置,可以在初始化flask的时候,设置template_folder

from flask import Flask
app = Flask(__name__,template_folder='./static/templates')

二、模板传参

render_template(template_name_or_list,**context) 中第一个参数为要渲染的模板或带有模板名称的迭代器,但指挥渲染第一个,第二个参数即为要传给前端的参数。

1.关键字传参

@app.route('/')
def hello_world():
    return render_template('index.html',username='Tom',password='123456')

对于username等,前端可以通过{ { username }}的形式直接使用。


<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>indextitle>
    head>
    <body>
        <h1>{
    { username }}h1>
        <h2>{
    { password }}h2>
    body>
html>

FLASK学习杂记(三)Flask模板_第6张图片

2.封装字典传参

@app.route('/')
def hello_world():
    dic = {
     
        'username':'Tony',
        'password':'123456z'
    }
    return render_template('index.html',dic = dic)

将所有要穿的参数封装成一个字典传dic给前端,前端可以通过{ {dic.username}}或{ {dic[‘username’]}}的形式取到


<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>indextitle>
    head>
    <body>
        <h1>{
    { dic.username }}h1>
        <h2>{
    { dic['password'] }}h2>
    body>
html>

FLASK学习杂记(三)Flask模板_第7张图片

3.**字典传参

首先将所有变量封装成字典,然后通过**传递。

@app.route('/')
def hello_world():
    context = {
     
        'username':'Tony',
        'password':'123456z',
        'score':{
     
            'Chinese':89,
            'math':96,
            'PE':70
    	}
    }
    return render_template('index.html',**context)

与封装成字典传参不同的是,**context传参前端可以直接通过所需参数名获取


<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>indextitle>
    head>
    <body>
        <h1>{
    { username }}h1>
        <h2>{
    { password }}h2>
        <h3>{
    { score.Chinese }}h3>
        <h3>{
    { score.math }}h3>
        <h3>{
    { score['PE'] }}h3>
    body>
html>

FLASK学习杂记(三)Flask模板_第8张图片

4.列表、元组、字典取用

@app.route('/')
def hello_world():
    dic = {
     
        'username':'Tony',
        'password':'123456z'
    }
    li = ['Jack','Tom']
    tup =(1,3,5)
    return render_template('index.html',li = li,tup=tup,dic = dic)

<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>indextitle>
    head>
    <body>
        <h1>{
    { li.0 }}h1>
        <h1>{
    { li[1] }}h1>
        <h2>{
    { tup.0 }}h2>
        <h2>{
    { tup[2] }}h2>
        <h3>{
    { dic.username }}h3>
        <h3>{
    { dic['password'] }}h3>
    body>
html>

FLASK学习杂记(三)Flask模板_第9张图片

三、模板基础

Flask采用Jinja2模板引擎,Jinja模板语法受Django和Python启发,有Python和Django基础更容易理解。

1.Jinja分隔符配置

  • {% … %}用于声明,如:{% for i in sep -%}
  • { { … }} 用于打印,如:{ { i }}
  • {# … #} 用于注释,类似
  • # … ## 行语句
@app.route('/')
def hello_world():
    li = ['Jack','Tom','Kitty']
    return render_template('index.html',li = li)

<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>indextitle>
    head>
    <body>
        <h1>
            {% for item in li%}
                {# 这里是注释的内容 #}
                {
    { item }}
            {% endfor %}
        h1>
    body>
html>

FLASK学习杂记(三)Flask模板_第10张图片

2.模板过滤器

内置过滤器

abs绝对值

@app.route('/')
def hello_world():
    li = [1,-2,3,-4]
    return render_template('index.html',li = li)

<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>indextitle>
    head>
    <body>
        <h2>
            {% for item in li %}
                {
    { item|abs }}
            {% endfor %}
         h2>
    body>
html>

FLASK学习杂记(三)Flask模板_第11张图片
capitalize首字母大写

@app.route('/')
def hello_world():
    li = ['tom','kitty','sindy','jack']
    return render_template('index.html',li = li)

<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>indextitle>
    head>
    <body>
        <h2>
            {% for item in li %}
                {
    { item|capitalize }}
            {% endfor %}
        h2>
    body>
html>

FLASK学习杂记(三)Flask模板_第12张图片
default
如果传入的变量为空,会打印定义好的文字,如果不为空要打印变量,需要设置boolean=true。


<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>indextitle>
    head>
    <body>
        <h2>
            {
    { is_null|default('this varity is not defined') }}
            <br>
            {
    { "--"|default('this varity is not defined',boolean=true) }}
        h2>
    body>
html>

FLASK学习杂记(三)Flask模板_第13张图片
dictsirt字典排序
dictsort可以按键或值对字典进行排序,用关键字by来控制,用reverse=true来控制升序,默认false,降序。


<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>indextitle>
    head>
    <body>
        <h2>
            原数据:
            <br>
            {
    { mydict }}
            <br>
            按键排序:
            <br>
            {% for item in mydict|dictsort(by ='key') %}
                {
    { item }}
            {%  endfor %}
            <br>
            按值排序 降序:
            <br>
            {% for item in mydict|dictsort(by ='value') %}
                {
    { item }}
            {%  endfor %}
            <br>
            按值排序 升序:
            <br>
            {% for item in mydict|dictsort(by ='value',reverse=true) %}
                {
    { item }}
            {%  endfor %}
            <br>
            {
    { mydict }}

        h2>
    body>
html>

FLASK学习杂记(三)Flask模板_第14张图片
可以看到dictsort排序不会对原数据进行修改。

escape转义
在字符串中,如果存在&,<,>等,需要转义成普通字符,才能避免被渲染成html元素,然在flask中会自动将这些字符转义成普通字符。


<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>indextitle>
    head>
    <body>
        <h3>
            {
    { '<h1>你好!; 北京。h1>' }}
        h3>
        <h2>
            {
    { '<h1>你好!; 北京。h1>'|e }}
        h2>
        <h1>
            {
    { '<h1>你好!; 北京。h1>'|escape }}
        h1>
    body>
html>

FLASK学习杂记(三)Flask模板_第15张图片
first、last、length
first返回元素第一项目,last返回最后一个元素,length返回元素长度


<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>indextitle>
    head>
    <body>
        <h3>
            {
    { 'hello'|first }}
        h3>
        <h2>
            {
    { 'hello'|last }}
        h2>
        <h1>
            {
    { 'hello'|length }}
        h1>
    body>
html>

FLASK学习杂记(三)Flask模板_第16张图片
join
将序列中的元素串联成字符串,默认串联符为空格。


<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>indextitle>
    head>
    <body>
        <h3>
            {
    { [1,2,3,4,5]|join }}
        h3>
        <h2>
            {
    { [1,2,3,4,5]|join(',') }}
        h2>
        <h1>
            {
    { [1,2,3,4,5]|join('->') }}
        h1>
    body>
html>

FLASK学习杂记(三)Flask模板_第17张图片
replace
替换元素中字符为另一个字符


<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>indextitle>
    head>
    <body>
        <h3>
            {
    { 'everyday,everynight'|replace('every','no') }}
        h3>
    body>
html>

FLASK学习杂记(三)Flask模板_第18张图片
其他过滤器
其他过滤器在此不做详细阐述,可以参考jinja官网上内置过滤器列表查看所有jinja过滤器。

自定义过滤器

通过装饰器template_filter()可以在后端自定义过滤器。

@app.template_filter('my_replace')
def rep(value):
    return value.replace('.','!')

<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>indextitle>
    head>
    <body>
        <h3>
            {
    { 'everyday,everynight.' }}
        h3>
        <h3>
            {
    { 'everyday,everynight.'|my_replace }}
        h3>

    body>
html>

FLASK学习杂记(三)Flask模板_第19张图片

3.结构控制

结构控制包括for循环、if/elif/else条件语句、宏以及块,用{% …%}来控制,每个控制语句要有对应的{% end… %}来结束。

for循环


<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>indextitle>
    head>
    <body>
        <h3>
            {% for item in ['Tom','Jack','Tony'] %}
                {
    { item }}
            {% endfor %}
        h3>
    body>
html>

FLASK学习杂记(三)Flask模板_第20张图片


<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>indextitle>
    head>
    <body>
        <h3>
            {% for item in [] %}
                {
    { item }}
            {%  else %}
                did not iterate
            {% endfor %}
        h3>
    body>
html>

FLASK学习杂记(三)Flask模板_第21张图片

如上,用{% endfor %} 来结束循环。

for-loop特殊变量访问
loop.index


<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>indextitle>
    head>
    <body>
        <h3>
            {% for item in ['Tom','Jack','Tony'] %}
                {# 从1开始的迭代 #}
                {
    { loop.index }}:{
    { item }}
                <br>
            {% endfor %}
        h3>
    body>
html>

FLASK学习杂记(三)Flask模板_第22张图片
loop.index0

<h3>
    {% for item in ['Tom','Jack','Tony'] %}
        {# 从0开始的迭代 #}
        {
    { loop.index0 }}:{
    { item }}
        <br>
    {% endfor %}
h3>

在这里插入图片描述
loop.revindex

<h3>
    {% for item in ['Tom','Jack','Tony'] %}
        {# 从item.length到1的迭代 #}
        {
    { loop.revindex }}:{
    { item }}
        <br>
    {% endfor %}
h3>

在这里插入图片描述
loop.revindex0

<h3>
    {% for item in ['Tom','Jack','Tony'] %}
        {# 从item.length-1到0的迭代 #}
        {
    { loop.revindex0 }}:{
    { item }}
        <br>
    {% endfor %}
h3>

在这里插入图片描述
loop.first

<h3>
    {% for item in ['Tom','Jack','Tony'] %}
        {# 是否为第一次迭代,返回布尔值 #}
        {
    { loop.first }}:{
    { item }}
        <br>
    {% endfor %}
h3>

在这里插入图片描述

loop.last

<h3>
    {% for item in ['Tom','Jack','Tony'] %}
        {# 是否为最后一次迭代,返回布尔值 #}
        {
    { loop.last }}:{
    { item }}
        <br>
    {% endfor %}
h3>

FLASK学习杂记(三)Flask模板_第23张图片
loop.length

<h3>
    {% for item in ['Tom','Jack','Tony'] %}
        {# 返回元素数目 #}
        {
    { loop.length }}:{
    { item }}
        <br>
    {% endfor %}
h3>

在这里插入图片描述
loop.cycle

<h3>
    {% for item in ['Tom','Jack','Tony'] %}
        {# 在指定元素中循环产生索引 #}
        {
    { loop.cycle('a','b') }}:{
    { item }}
        {
    { loop.cycle('a','b','c','d') }}:{
    { item }}
        <br>
    {% endfor %}
h3>

在这里插入图片描述
loop.depth、loop.depth0

<h3>
    {% for item in ['Tom','Jack','Tony'] %}
        {# 迭代深度,从1开始 #}
        {
    { loop.depth }}:{
    { item }}
         <br>
        {# 迭代深度,从0开始 #}
        {
    { loop.depth0 }}:{
    { item }}
        <br>
    {% endfor %}
h3>

在这里插入图片描述

loop.previtem

<h3>
    {% for item in ['Tom','Jack','Tony'] %}
        {# 查看元素的前一个元素 #}
        {
    { loop.previtem }}:{
    { item }}
        <br>
    {% endfor %}
h3>

在这里插入图片描述
loop.nextitem

<h3>
    {% for item in ['Tom','Jack','Tony'] %}
        {# 查看元素的后一个元素 #}
        {
    { loop.nextitem }}:{
    { item }}
        <br>
    {% endfor %}
h3>

在这里插入图片描述

条件语句


<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>indextitle>
    head>
    <body>
        <h3>
            {% for item in ['about','boy','kill'] %}
                {
    { item }}
                {% if item|first =='a' %}
                    该字母以a开头
                {%  elif item|first == 'b' %}
                    该字母以b开头
                {%  else %}
                    该字母不以a、b开头
                {%  endif %}
                <br>
            {% endfor %}
        h3>
    body>
html>

FLASK学习杂记(三)Flask模板_第24张图片

可以将宏理解为函数,复用功能,以避免代码重复,可以传参但没有返回值。
用{% macro name(parameter1,parameter2,…) %}的形式来定义宏,parameter为参数,可以设置默认值。


<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>indextitle>
    head>
    <body>
    {% macro input(name,value='',type='text',size=20) %}
        
    {% endmacro %}

    <p>用户名:{
    { input('username') }}p>
    <p>   码:{
    { input('password',type='password') }}p>
    <p>{
    { input('提交',type='submit') }}p>
    body>
html>

FLASK学习杂记(三)Flask模板_第25张图片
import宏
在世纪开发中,会把宏放入一个单独的html文件中,在使用的时候需要导入
macro.html文件


<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>macrotitle>
head>
<body>
{% macro input(name,value='',type='text',size=20) %}
        
{% endmacro %}
body>
html>

index.html
import

{% import 'macro.html' as marco %}

<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>indextitle>
    head>
    <body>
    <p>用户名:{
    { marco.input('username') }}p>
    <p>   码:{
    { marco.input('password',type='password') }}p>
    <p>{
    { marco.input('提交',type='submit') }}p>
    body>
html>

from … import …

{% from 'macro.html' import input  %}

<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>indextitle>
    head>
    <body>
    <p>用户名:{
    { input('username') }}p>
    <p>   码:{
    { input('password',type='password') }}p>
    <p>{
    { input('提交',type='submit') }}p>
    body>
html>

FLASK学习杂记(三)Flask模板_第26张图片

块和模板继承

块的存在为jinjia模板继承提供了很大的便利,用{% block name %}来定义,每个块结束都由对应的{% endblock %} 来控制,也可用{% endblock name %} 来结束以增加可读性。

*{
     
    margin: 0;
    padding: 0;
}

.bg{
     
    width: 1500px;
    height: 50px;
    background-color: #e7b434;
}

#top{
     
     background-color: antiquewhite;
}

#footer{
     
    background-color: #6d6a6a;
}

父模板


<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>
        {%  block title%}
        base
        {%  endblock %}
    title>
    <link rel="stylesheet" href="{
      { url_for('static',filename='css/base.css') }}">
head>
<body>

<div id="top" class="bg">
div>
<div class="bg">
    {% block center %}
    <h1>这里是要被继承的父模块h1>
    {% endblock %}
div>
<div id="footer" class="bg">div>
body>
html>
@app.route('/block/')
def block():
    return render_template('base.html')

FLASK学习杂记(三)Flask模板_第27张图片

子模块

{% extends 'base.html' %}

{% block title %}
extend
{% endblock %}

{% block center %}
<h2>这是继承了父模板的子模板h2>
{% endblock %}
@app.route('/extendblock/')
def extendblock():
    return render_template('extend.html')

FLASK学习杂记(三)Flask模板_第28张图片
可以看到子模块中只需要修改被block包裹的部分即可。
用super()调用父块结果:

{% extends 'base.html' %}

{% block title %}
extend
{% endblock %}

{% block center %}
<h2>这是继承了父模板的子模板h2>
    {
    { super() }}
{% endblock %}

FLASK学习杂记(三)Flask模板_第29张图片
可以看到父块的结果被返回。
嵌套扩展

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

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

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

parent


<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>
        {% block title %}
        Parent
        {% endblock %}
    title>
head>
<body>
body: {% block body %}This is from parent.{% endblock %}
body>
html>

child

{% extends 'parent.html' %}
{% block title %}Child
{% endblock%}

{% block body %} This is Child. {
    { super() }}
{% endblock %}

grandchild

{% extends 'child.html' %}
{% block title %} Grandchild{% endblock %}
{% block body %}This is grandchild.
{
    { super.super() }}
{% endblock %}

parent
FLASK学习杂记(三)Flask模板_第30张图片
child
FLASK学习杂记(三)Flask模板_第31张图片
grandchild
用super.super()可以引用parent。
FLASK学习杂记(三)Flask模板_第32张图片

set

可以理解成定义变量并赋值,有作用域限制,在块内设置的变量无法现实在块外,循环中设置的也无法显示在循环外。如下,在循环内外set一个相同的item,


<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>settitle>
head>
<body>
{% set item = 0 %}
{% for i in [1,2,3] %}
    i = {
    { i }}
    {% set item = i %}
    item = {
    { item }}
    <br>
{% endfor %}
{% if item == 0%} item {% endif %}
body>
html>

FLASK学习杂记(三)Flask模板_第33张图片
如果想实现跨作用域传播,可以通过namespace的方法。
如下,通过namespace() set n.flage = false,n.s=1


<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>settitle>
head>
<body>
{% set n = namespace(flage=false,s=1) %}
{% for item in [1,2,3,4] %}
    {
    { item }}
    {% if item > 3%}
        {% set n.flage = true %}
        {% set n.s = item %}
    {% endif %}
    <br>
{% endfor %}
n.flage:{
    { n.flage }},n.s:{
    { n.s }}
body>
html>

FLASK学习杂记(三)Flask模板_第34张图片

4.Jinjia表达式

Jinjia表达式与python非常相似,有python基础的更好理解,这里只稍微列举,详细请见Jinjia官网

  • 元组:(’a’,‘b’,‘c’);
  • 列表:[1,2,3] ;
  • 字典:{“user”:“Tom”,“password”:123456}
  • 数学运算 : +(加)、-(减)、*(乘)、%(除)、**(幂)…
  • 比较:== 、!=、>、<、<=、>=
  • 逻辑:and 、 or 、not 、expr
  • 其他:in 、is…

你可能感兴趣的:(flask,python,flask)