Python 测开28期 - WL - 学习笔记 - 静态文件与模板技术

后端开发 - 静态文件与模板技术

静态文件

  • 静态文件:static files,和模板概念相反,指内容不需要动态生成的文件
    • 比如图片、CSS文件和JavaScript 脚本等
  • 添加方法
    • 创建 static 目录,它一共和程序模块、templates 在同一目录层级

生成静态文件 URL

  • 通过 url_for() 函数来生成
    • 此函数在python脚本中,需要从 flask 包中导入
    • 模板中可以直接使用
    • 对于静态文件,此函数需要传入的路由就是 static,同时使用 filename 参数传入相对于 static 文件夹的文件路径
    • 花括号部分的调用会返回 /static/pic.jpg
<img src="{{ url_for('static', filename='pic.jpg' ) }}>
添加图标
    1. 准备一个或 ico、png、gif格式的图片,大小一般是 1616、3232、4848、6464
  • 把该图片放入 static 目录下,然后在html模板中引用
from flask import Flask, render_template

# 创建 Flask 应用程序实例
app = Flask(__name__)

# 定义路由和视图函数
@app.route("/")
def show_static():
    return render_template("tatic.html")
    
# 运行应用程序
if __name__ == '__main__':
    app.run(debug=True, port=5050)
    1. 在 templates 目录下创建 static.html
    • 需要放在head标签中
    • 通过 link 标签进行链接
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" cintent="width=device-width, initial-scale=1.0" />
    <title>静态文件</title>
    <link rel="icon" href="{{ url_for('static', filename='logo.png') }}">
</head>
<body>
    <h1>静态文件</h1>
</body>
</html>
<script type="text/javascript"></script>
    1. 启动服务,访问浏览器,在浏览器标签页可见此图标

添加图片

    1. 在 static 目录下创建子文件夹 images,把图片都放到这个文件夹中
    • 创建子文件夹并不是必须的,
    • 同样如果有多个 CSS 文件,也可以创建一个 css 文件夹来管理
    • 注意路径要写正确
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" cintent="width=device-width, initial-scale=1.0" />
    <title>静态文件</title>
    <link rel="icon" href="{{ url_for('static', filename='logo.png') }}">
</head>
<body>
    <h1>
        <img alt="branch" src="{{ url_for('static', filename='images/branch.gif') }}">霍格沃兹
    </h1>
    <div>
        <img ail="Gryffindor' src="{{ url_for('static', filename='images/Gryffindor.png') }}">
        <img ail="hogwarts' src="{{ url_for('static', filename='images/hogwarts.jpg') }}">
    </div>
</body>
</html>
<script type="text/javascript"></script>

添加 CSS 文件

  • 添加图片与文件,没有排版样式,需要添加CSS定义
    1. 在 static 目录下创建一个 CSS文件 style.css
body {
    margin: auto;
    max-width: 800px;
    font-size: 14px;
    font-family: Helvetiva, Arial, sans-serif;
}

/* 霍格沃兹学院 */
.hogwarts {
    display: auto;
    margin: 0 auto;
    height: 300px;
}

/* 小图片 */
.pic {
    width: 100px;
}
    1. 在 static.html 页面的标签内引入此 CSS 文件
<head>
    <link rel="stylesheet" href="{{ url_for('statuc', filename='style.css) }}">
</head>
    1. 为对应的元素设置 class 属性,和对应的 CSS 定义关联起来,
    • templates/index.html:添加 class属性
<body>
    <h1>
        <img alt="branch" class="pic" src="{{ url_for('static', filename='images/branch.gif') }}">霍格沃兹
</h1>
<div>
    <img ail="Gryffindor' class="pic" src="{{ url_for('static', filename='images/Gryffindor.png') }}">
    <img ail="hogwarts' class="hogwarts" src="{{ url_for('static', filename='images/hogwarts.jpg') }}">
</div>
</body>
</html>
<script type="text/javascript"></script>

模板技术

渲染模板

  • 定义:web程序里,访问一个地址通常会返回一个包含各类信息的HTML页面,其中包含变量和运算逻辑的HTML或其他合适的文本叫做模板
  • 执行这些变量替换和逻辑计算工作的过程称为渲染
  • Flask 模板是xuan’ra通过 Jinja2 引擎来完成的
  • 默认,Flask 会从模块同级的 templates 目录下寻找模板
应用场景价值
  • 动态内容:Flask 模板支持将动态数据插入HTML页面,从而创建个性化和交互式的 Web 应用程序
  • 代码重用:模板允许在多个页面之间重用常见的HTML组件,减少冗余代码,提高可维护性
  • 一致的设计:通过使用模板,可以确保应用程序在设计和布局上保持一致,从而实现专业和统一的用户体验
  • 与其他技术的集成:Flask 模板可以与其他前端技术(如CSS框架和JavaScript库) 集成,实现现代化和视觉上吸引人的 Web 界面
模板渲染
    1. 在项目中创建模板目录,目录名称固定为:templates
    1. 在 templates 目录中创建HTML文件,创建完成后,结构如下
./
├── xx.py
└── templates
    └── hogwarts.html

    1. 在 html文件中写入内容:
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Hogwarts</title>
  </head>
  <body>
    <h1>霍格沃兹平台</h1>
  </body>
</html>
<script type="text/javascript"></script>
    1. 视图函数的返回使用 render_template() 渲染对应的HTML文件,如下:
from flask import Flask, render_template

# 创建 Flask 应用程序实例
app = Flask(__name__)

@app.route("/")
def hello():
    return render_template("hogwarts.html")

# 运行应用程序
if __name__ == '__main__':
    app.run(port=5055, debug=True)
    1. 启动服务,访问默认地址,接口看到渲染的HTML页面

模板语法

  • 使用 Jinja2 模板引擎
  • 可以放入一部分程序逻辑到模板中处理,但是并不支持所有的python语法
  • 尽量仅把和输出控制有关的逻辑操作放到模板当中
  • Jinja2 允许模板使用大部分python对象,
    • 字符串、列表、字典、元组、整型、浮点型、布尔值,
    • 支持基本运算符号: +、-、*、/,等
    • 支持比较符号:==、!=,等
    • 支持逻辑符号:and、or、not和括号
    • 支持:in、is、None、和布尔值–True、False
  • 变量代码块{{ }}:主要用于变量的内容显示
  • 控制代码块{% %}:主要用于涉及到与逻辑相关的代码块展示
传递数据
  • 调用 render_template() 方法时,可以使用关键字传参
    1. 在html的body标签中添加代码,其中 {{ name }}代表模板中所包含的变量信息
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Hogwarts</title>
  </head>
  <body>
    <h1>霍格沃兹平台</h1>
    <h2>{{ name }}</h2>
  </body>
</html>
<script type="text/javascript"></script>
    1. 视图函数中调用方法 render_template(‘hogwarts.html’, name=‘aaabbb’)的时候,通过关键字传参到html页面当中
from flask import Flask, render_template

# 创建 Flask 应用程序实例
app = Flask(__name__)


@app.route("/data")
def hogwarts():
    return render_template("hogwarts.html", name="hogwarts")

# 运行应用程序
if __name__ == '__main__':
    app.run(port=5055, debug=True)
    1. 启动服务,访问 /data 路由,name变量的位置会展示传入的值,
判断语法
  • Flask 中的 Jinja2 模板提供了多种控制结构,
# 条件控制语句
<!-- if 条件判断--->
{% if 条件表达式 %}
.......
{% elif 条件表达式 %}
.......
{% else %}
.......
{% endif %}
  • 示例
from flask import Flask, render_template

# 创建 Flask 应用程序实例
app = Flask(__name__)


@app.route("/person")
def person():
    person = {
        "name": "lily",
        "age": 18,
        "gender": "female"
    }
    return render_template("person.html", person=person)

# 运行应用程序
if __name__ == '__main__':
    app.run(port=5055, debug=True)
  • templates 目录下创建 person.html 文件
    • 模板中,Jinja2 支持使用 点 . 获取变量的属性,比如person字典中的gender简直通过 . 获取,即 person.gender
<!-- person.html -->

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Title</title>
  </head>
  <body>
    <p>
      您好, 
      {% if person.gender == "male" %} 
        {{ person.name }} 先生 
      {% else %}
      {{ person.name }} 女士 
      {% endif %}
    </p>
  </body>
</html>
<script type="text/javascript"></script>
  • 启动服务,访问 /person 路由,可根据判断结果显示对应的信息
循环语法
  • for 语句来迭代一个序列,语法如下
<!-- for 循环 -->
{% for row in list_or_dict %}
{{ row }}
{% endfor %}
  • 示例
from flask import Flask, render_template

# 创建 Flask 应用程序实例
app = Flask(__name__)


@app.route("/people")
def people():
    people = [
        {
            "name": "lily",
            "age": 18,
            "gender": "female"
        },
        {
            "name": "tom",
            "age": 19,
            "gender": "male"
        },
    ]
    return render_template("people.html", people=people)

# 运行应用程序
if __name__ == '__main__':
    app.run(port=5055, debug=True)
  • templates 目录下创建 people.html文件
<!-- people.html -->

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Title</title>
  </head>
  <body>
    {% for p in people %}
    <p>
      Hello, 
      {% if p.gender == "male" %} 
        Mr. {{ p.name }} 
      {% else %} 
        Ms. {{ p.name }}<br />
      {% endif %} 
      Your age is {{ p.age }}<br />
      Your gender is {{ p.gender }}<br />
    </p>
    {% endfor %}
  </body>
</html>
<script type="text/javascript"></script>
  • 启动服务,访问 /people 路由,页面中会显示所有的人员信息,并通过性别来判断显示信息
继承语法
  • 模板继承允许创建一个基础的骨架模板,包含网站的通用元素,并且定义子模板可以重载的区域
  • 举例:顶部的导航栏、底部的页脚部分,等等
  • 将这些相同的内容集合放入父模板中,不同的地方使用其他东西展位,然后在不同的页面中继承这个父模板,再填充不同的内容
    1. 定义父模板 语法
    • 标签 block 用于在父模板中预留区域,留给子模版填充差异性内容,名字不能相同,父模板也可以使用上下文中传递过来的数据
<!-- 父模版中定义,子模板可以直接继承重写 -->
{% block 自定义名称 %} 

{% endblock %}
    1. 子模版继承父模板 语法
{% extends '父模板' %}
  • 示例
      1. layout.html 文件是父模板,也可以看成一个骨架,可以让继承者对 title、content、footer三个地方进行定制
<!-- layout.html -->

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>{% block title %}{% endblock %}</title>
    </head>
    <body>
        <div id="content">{% block content %}{% endblock %}</div>
        <div id="footer">
            {% block footer %} &copy; Copyright 2023 by
            <a href="https://ceshiren.com">测试人社区</a>. {% endblock %}
        </div>
    </body>
</html>
<script type="text/javascript"></script>
    1. son.html 文件是子模版,用来继承父模板,并对title、content机械能定会之
<!-- son.html -->

{% extends "layout.html" %} 

{% block title %}Son Page{% endblock %} 

{% block content %}

<h1>子模版</h1>
<button>按钮</button>

{% endblock %}
    1. 定义视图函数–接口函数,返回子模版的HTML文件
from flask import Flask, render_template

# 创建 Flask 应用程序实例
app = Flask(__name__)

@app.route("/extend")
def extend():
return render_template("son.html")

# 运行应用程序
if __name__ == '__main__':
app.run(port=5055, debug=True)
    1. 启动服务,访问路由后,展示对应页面
模板导入
  • 定义:将另一个模板加载到当前模板中,直接渲染,
  • 模板继承和类的继承含义是一样的,
  • 为了提高代码重用,减轻开发工作量
  • 导入语法
{% include '文件名' %}
  • 示例
    • 创建顶部栏页面 top.heml
<a>首页</a>
<a>关于</a>
  • 在 som.html 中导入 top.html
{% extends "layout.html" %}

{% block title %}Son Page{% endblock %}

{% include "top.html" %}

{% block content %}
<h1>子模版继承</h1>
<button>按钮</button>
{% endblock %}
  • 导入 top.html,该模板直接加载并渲染到当前模块中
导入列表
  • 也可以导入一个模板列表,程序会按照顺序一次寻找模板文件,
  • 第一个被找到的模板文件将被加载渲染,后续的会忽略
{% include ['footer.html','bottom.html','top.html'] %}
忽略报错
  • 如果都没有找到模板,程序会报错,要忽略报错,需要增加 ignore missing,用来忽略 include 语句
{% include ['footer/html','bottom.html','end.html'] ignore missing %}