在本实训中,将开始编写“致敬长征”项目中的影视作品列表页,在本页面中以列表的形式展示与长征相关的影视作品信息。通过自定义函数的方式实现从相关的json文件中加载示例数据,并通过render_template()方法将数据传递给模板文件,最后在模板文件中接收数据,并将数据渲染到模板的合适位置。具体步骤如下:
1.与实训8中的长征概述页实现类似,在影视作品列表页中也需要实现从项目框架根目录下的/static/jsons子目录下加载示例数据,然后渲染到模板中的操作。考虑到后续的其它模块中也需要类似的操作,因此,将从josn文件中加载数据的功能封装到一个函数中,以实现代码的复用。首先在项目根目录下的utils子目录,创建一个名为load_data.py的文件,如图1所示: 2. 编辑刚创建的load_data.py文件,如图2所示。在文件中定义一个用于从json文件中加载数据的函数:load_data_from_json_file(),在函数中接收两个参数:target为要读取的json文件相对于项目根目录的相对路径,project_name接收一个表示项目名称的字符串,以用于准确的构建目标文件的完整路径。在函数的第15行代码通过字符串的split方法,得到项目所在的父目录,然后在第16行通过os.path模块的join()方法拼接出目标文件的完整路径。第17-32行代码利用with语句及json模块的load()方法实现json数据的加载,因示例数据文件中json对象的键的命名方式采用的是驼峰命名格式,而Python中推荐的标识符命名格式为下划线分割的格式,因此第24-29行代码对从json文件中加载进来的数据将键的命名方式进行转换修改,具体执行转换工作的为第35-38行代码处定义的to_snake_case()函数,在函数中利用正则表达式的功能实现转换功能,关于正则表达式的知识将在后续的章节中进行介绍,load_data.py的完整代码如图2中所示。
import json
import os
import re
def load_data_from_json_file(target, project_name=None):
"""
从json文件中加载数据,并将数据返回
:param target: json文件在当前项目中的相对路径
:param project_name: 当前项目的项目名称
:return: 一个包含数据的列表,每个列表项为一个字典对象;或返回None
"""
if not project_name:
project_name = '致敬长征'
base_path = os.getcwd().split(project_name)[0]
fpath = os.path.join(base_path, project_name, target) # 构造示例数据文件的路径字符串
if os.path.exists(fpath): # 如果数据文件存在,读取并返回数据
# 用open方法,根据示例数据文件路径打开json文件,并用json模块的load方法将数据加载到相应变量中
with open(fpath, mode='r', encoding='utf-8') as fp:
infos = json.load(fp=fp)
if isinstance(infos, dict):
infos = [infos]
results = []
for info in infos:
temp = {}
# 循环处理示例数据中的每一个键值对,将键的命名方式修改为Python推荐的下划线分隔的格式
for key, value in info.items():
temp[to_snake_case(key)] = value
results.append(temp)
return results
else:
return None
def to_snake_case(name):
# 使用正则表达式将驼峰命名格式(如:heLLoWorLd)转换为下划线分隔的格式(如:heLLo_worLd)
s = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', name)
return re.sub('([a-z0-9])([A-Z])', r'\1_\2', s).lower()
3. 编辑项目根目录下的views子目录中的cz_video.py文件,如图3所示:在视图函数video_list_page()中添加相应代码:第12行代码给出目标json文件相对于项目根目录的路径字符串,第14行代码调用上面创建的load_data_from_json_file()函数实现从cz_video.json文件中加载数据,第17行代码处通过render_template()方法将影视作品列表数据渲染到模板文件:cz_video_list.html中。
import json
import os
from flask import Blueprint, render_template
from utils.load_data import load_data_from_json_file
video = Blueprint('video', __name__, url_prefix='/video') # 创建名为”video“的蓝图
@video.route('/video_list')
def video_list_page():
target_file = r"static/jsons/cz_video.json" # 构造示例数据文件的路径字符串
# 调用 utils.load_data块下的load_data_from_json_file方法,从json文件加载数据
video_list = load_data_from_json_file(target=target_file)
# 利用render_template方法,将相关数据渲染到模板文件中
return render_template("/video/cz_video_list.html", video_list=video_list)
4. 编辑模板文件:cz_video_list.html,代码如图4所示:
{% extends "cz_base.html" %}
{% block title %} 影视作品列表 {% endblock %}
{% block links %}
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='css/cz_video_style.css') }}">
{% endblock %}
{% block main %}
<div class="album py-5">
<div class="container">
<div class="row row-cols-1 row-cols-sm-2 row-cols-md-3 g-3">
{% for v in video_list %}
<div class="col">
<div class="card shadow-sm">
<img class="bd-placeholder-img card-img-top" height="225" src="{{ url_for('static', filename=v.video_pic) }}">
<div class="card-body">
<p class="card-text">{{ v.video_description }}</p>
<div class="d-flex justify-content-between align-items-center">
<div class="btn-group">
<a class="btn btn-sm btn-outline-secondary">查看详情</a>
</div>
<small class="text-muted h5 fw-bolder">{{ v.video_publisher }}</small>
</div>
</div>
</div>
</div>
{% endfor %}
</div>
</div>
</div>
{% endblock %}
5. 完成以上步骤的代码编写后,运行项目,在浏览器地址栏中输入对应的URL地址(例如:http://127.0.0.1:19999/video/video_list)。应该能看到页面的呈现效果如图5所示。