您的位置:首页 > 房产 > 建筑 > 【Flask从入门到精通:第六课:终端脚本命令、Jinja2模板引擎】

【Flask从入门到精通:第六课:终端脚本命令、Jinja2模板引擎】

2025/3/10 21:54:39 来源:https://blog.csdn.net/weixin_50556117/article/details/140367560  浏览:    关键词:【Flask从入门到精通:第六课:终端脚本命令、Jinja2模板引擎】

终端脚本命令

在flask1.1版本之前版本中都是采用flask-script模块来执行终端脚本命令,flask1.1版本以后不再使用这个模块了,因为存在兼容性问题。

flask1.0的终端命令使用

flask-script模块的作用可以让我们通过终端来控制flask项目的运行,类似于django的manage.py

官方文档:https://flask-script.readthedocs.io/en/latest/

安装命令:

pip install -U flask==1.1.4
pip install flask-script -i https://pypi.douban.com/simple

集成 Flask-Script到flask应用中,创建一个主应用程序,一般我们叫manage.py/run.py/main.py都行。

manage.py,代码:

from flask import Flas app = Flask(__name__)"""使用flask_script启动项目"""
from flask_script import Manager
manage = Manager(app)@app.route('/')
def index():return 'hello world'if __name__ == "__main__":manager.run()

启动终端脚本的命令:

# 端口和域名不写,默认为127.0.0.1:5000
python manage.py runserver# 通过-h设置启动域名,-p设置启动端口 -d
python manage.py runserver -h0.0.0.0 -p8888     # 关闭debug模式
python manage.py runserver -h0.0.0.0 -p8888  -d # 开启debug模式# 进入flask交互终端,在这个终端下,可以直接调用flask代码进行测试。
python manage.py shell

自定义终端命令

Flask-Script 还可以为当前应用程序添加脚本命令

1. 引入Command命令基类
2. 创建命令类必须直接或间接继承Command,并在内部实现run方法或者__call__()方法,同时如果有自定义的其他参数,则必须实现get_options方法或者option_list属性
3. 使用flask_script应用对象manage.add_command对命令类进行注册,并设置调用终端别名。

manage.py,代码:

from abc import ABCfrom flask import Flask
from flask_script import Manager, Command, Optionapp = Flask(__name__)
# 配置
app.config.update({"DEBUG": False,"SECRET_KEY": "sklaasle3k2334"
})"""使用flask_script启动项目"""
manager = Manager(app)class PrintCommand(Command, ABC):"""命令的相关描述: 打印数据"""def get_options(self):options = (# Option('简写选项名', '参数选项名', dest='变量名', type=数据类型, default="默认值"),Option('-h', '--host', dest='host', type=str, default="127.0.0.1"),Option('-p', '--port', dest='port', type=int, default=8000),Option('-d', '--debug', dest='debug', type=bool, default=False))# 必须返回选项return options# 也可以使用option_list来替代get_options# option_list = (#     Option('-h', '--host', dest='host', type=str, default="127.0.0.1"),#     Option('-p', '--port', dest='port', type=int, default="7000"),#     Option('-d', '--debug', dest='debug', type=bool, default=False)# )# 没有flask的应用实例对象---->app对象# def run(self, host, port, debug):#     print("测试命令")#     print(f"self.host={host}")#     print(f"self.port={port}")#     print(f"self.debug={debug}")def __call__(self, app, host, port, debug):  # 会自动传递当前flask实例对象进来print("测试命令")print(f"self.host={host}")print(f"self.port={port}")print(f"self.debug={debug}")# manage.add_command("终端命令名称", 命令类)
manager.add_command("print", PrintCommand)@app.route("/")
def index():return "ok"if __name__ == '__main__':manager.run()

使用效果:

(flask) moluo@ubuntu:~/Desktop/flaskdemo$ python manage.py print -h=0.0.0.0 -p 8000
测试命令
self.host=0.0.0.0
self.port=8000
self.debug=False(flask) moluo@ubuntu:~/Desktop/flaskdemo$ python manage.py print -h=0.0.0.0 -p 8000 -d=true
测试命令
self.host=0.0.0.0
self.port=8000
self.debug=True(flask) moluo@ubuntu:~/Desktop/flaskdemo$ python manage.py print -h=0.0.0.0 -d=true
测试命令
self.host=0.0.0.0
self.port=8000
self.debug=True

flask2.0的终端命令使用

flask0.11.0版本以后,flask内置了一个Click模块,这个模块是终端命令模块,可以让我们直接通过Click的装饰器,编写和运行一些终端命令。在flask2.0版本已经不能兼容flask-script模块了,所以需要改成使用Click模块来运行和自定义管理终端命令了。

文档地址:https://dormousehole.readthedocs.io/en/latest/cli.html#id10

click文档:https://click.palletsprojects.com/en/8.0.x/

pip install -U flask==2.0.2

安装了flask2.0以后,当前项目所在的python环境就提供了一个全局的flask命令,这个flask命令是Click提供的。

# 要使用Click提供的终端命令flask,必须先在环境变量中声明当前flask项目的实例对象所在的程序启动文件。
# 例如:manage.py中使用了 app = Flask(__name__),则manage.py就是程序启动文件# 使用flask终端命令之前,可以配置2个环境变量。
# 指定入口文件,开发中入口文件名一般:app.py/run.py/main.py/index.py/manage.py/start.py
export FLASK_APP=manage.py
# 指定项目所在环境
export FLASK_ENV=development   # 开发环境,默认开启DEBUG模式
# export FLASK_ENV=production   # 生成环境,默认关闭DEBUG模式

默认情况下,flask命令提供的子命令。

flask routes  # 显示当前项目中所有路由信息
flask run     # 把flask项目运行在内置的测试服务器下
# flask run --host=0.0.0.0 --port=5055
flask shell   # 基于项目的应用上下文提供终端交互界面,可以进行代码测试。

Click自定义终端命令

import click
from flask import Flask, viewsapp = Flask(__name__)
# 配置
app.config.update({"DEBUG": False,
})# 自定义终端命令
@app.cli.command("faker")                                                # 假设这个用于生成测试数据
@click.argument("data", default="user")                                  # data表示生成数据的类型[参数argument是命令调用时的必填参数]
@click.option('-n', 'number', type=int, default=1, help='生成的数据量.')   # num表示测试数据的生成数量[选项option是命令调用时的可选参数]
def faker_command(data, number):"""添加测试信息"""print("添加测试信息")print(f"数据类型:data={data}")print(f"生成数量:number={number}")@app.route("/")
def index():return "ok"if __name__ == '__main__':app.run()"""
flask faker --help
flask faker -n10 user
flask faker user
"""

终端下的运行效果:

(flask) moluo@ubuntu:~/Desktop/flaskdemo$ flask faker -n10 user
添加测试信息
数据类型:data=user
生成数量:number=10
(flask) moluo@ubuntu:~/Desktop/flaskdemo$ flask faker user
添加测试信息
数据类型:data=user
生成数量:number=1
(flask) moluo@ubuntu:~/Desktop/flaskdemo$ flask faker goods
添加测试信息
数据类型:data=goods
生成数量:number=1

练习:

1. flask2.0的终端下,输入 python manage.py startapp home 则可以在当前目录下创建以下目录和文件
项目目录/└── home├── views.py├── models.py├── urls.py└── tests.py

代码:

import click, os
from flask import Flaskapp = Flask(__name__)
# 配置
app.config.update({"DEBUG": False
})@app.cli.command("startapp")
@click.argument("name")
# @click.option('-n', 'name', help='app name')
def startapp(name):"""生成子模块或子应用"""if os.path.isdir(name):print(f"当前{name}目录已存在!请先处理完成以后再创建。")returnos.mkdir(name)open(f"{name}/views.py", "w")open(f"{name}/models.py", "w")open(f"{name}/documents.py", "w")open(f"{name}/ws.py", "w")open(f"{name}/services.py", "w")open(f"{name}/urls.py", "w")open(f"{name}/test.py", "w")print(f"{name}子应用创建完成....")@app.route("/")
def index():return "ok"if __name__ == '__main__':app.run()

终端调用:

flask startapp home
flask startapp users

在这里插入图片描述

Jinja2模板引擎

Flask内置的模板语言Jinja2,它的设计思想来源于 Django 的模板引擎DTP(DjangoTemplates),并扩展了其语法和一系列强大的功能。

  • Flask提供的 render_template 函数封装了该模板引擎Jinja2
  • render_template 函数的第一个参数是模板的文件名,后面的参数都是键值对,表示模板中变量对应的数据值。

模板基本使用

  1. 在flask应用对象创建的时候,设置或者保留template_folder参数,创建模板目录

    app = Flask(__name__,template_folder='templates')
    
  2. 在项目下手动创建 templates 文件夹,用于存放所有的模板文件,并在目录下创建一个模板html文件 index.html

    <!doctype html>
    <html lang="en">
    <head><meta charset="UTF-8"><title>{{ title }}</title>
    </head>
    <body><h1>{{ content }}</h1>
    </body>
    </html>
    
  3. 在视图函数设置渲染模板并设置模板数据

    from flask import Flask, render_template# 默认情况下,flask默认直接支持视图加载模板的。
    # Flask类在实例化的时候,默认当前根目录下的templates目录作为模板目录
    app = Flask(__name__, template_folder="templates")
    # 配置
    app.config.update({"DEBUG": True
    })@app.route("/")
    def index():data = {"title": "我的模板标题","content": "我的模板内容"}return render_template("index.html", **data)@app.route("/user/<id>")
    def user(id):title = "User Center"content = "我的个人中心"print(locals()) # {'id': '100', 'title': 'User Center', 'content': '我的个人中心'}return render_template("user.html", **locals())if __name__ == '__main__':app.run()

输出变量

{{ 变量名 }},这种 {{ }} 语法叫做 变量代码块

视图代码:

import click
from flask import Flask,render_template
# flask开发小型的项目,直接在当前flask应用配置即可。手动创建模板目录。
# flask开发中大型项目,直接在当前flask的每一个子应用(蓝图)下构建目录。
app = Flask(import_name=__name__, template_folder="templates")# 配置类
class Config(object):DEBUG = True  # 开启调试模式# 加载配置
app.config.from_object(Config)@app.route("/")
def index():title = "站点标题"user_list = [{"id":1, "name": "xiaoming", "age":16},{"id":2, "name": "xiaoming", "age":16},{"id":3, "name": "xiaoming", "age":16},]return render_template("index.html", **locals())if __name__ == '__main__':app.run()

模板代码

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>{{title}}</title>
</head>
<body><h1>{{title}}</h1><p>{{ user_list.0 }}</p><p>{{ user_list.0.name }}</p>
</body>
</html>

pycharm中设置当前项目的模板语言:

files/settings/languages & frameworks/python template languages。

设置下拉框为jinja2,保存

在这里插入图片描述

设置指定目录为模板目录,鼠标右键->Mark Directory as …-> Template Folder

在这里插入图片描述

Jinja2 模版中的变量代码块的输出的内容可以是Python的任意类型数据或者对象,只要它能够被 Python 的 __str__ 方法或者str()转换为一个字符串就可以,比如,可以通过下面的方式显示一个字典或者列表中的某个元素:

视图代码:

from flask import Flask, render_templateapp = Flask(__name__, template_folder="templates")@app.route("/")
def index():title = "我的flask"data_list = ["a", "b", "c"]data_dict = {"name": "xiaoming","id": 100,}user_list = [{"id":1, "name": "xiaoming", "age":16},{"id":2, "name": "xiaoming", "age":16},{"id":3, "name": "xiaoming", "age":16},]return render_template("index.html", **locals())if __name__ == '__main__':app.run(host="0.0.0.0", port=5000, debug=True)

模板代码:

<!doctype html>
<html lang="en">
<head><meta charset="UTF-8"><title>{{ title }}</title>
</head>
<body><h1>{{ title }}!!</h1><p>{{ data_list }}</p><p>{{ data_list.1 }}</p><p>{{ data_list[-1]}}</p><p>{{ data_list | last }}</p><p>{{ data_list | first }}</p><p>{{ data_dict }}</p><p>{{ data_dict.name }}</p><p>{{ user_list.0 }}</p><p>{{ user_list.0.name }}</p>
</body>
</html>

使用 {# #} 进行注释,注释的内容不会在html中被渲染出来

{#    <h1>{{ title }}!!</h1>#}
{#    <p>{{ data_list }}</p>#}
{#    <p>{{ data_list.1 }}</p>#}<p>{{ data_list[-1]}}</p><p>{{ data_list | last }}</p><p>{{ data_list | first }}</p><p>{{ data_dict }}</p><p>{{ data_dict.name }}</p><p>{{ user_list.0 }}</p>
{#    <p>{{ user_list.0.name }}</p>#}

模板中内置的变量和函数

你可以在自己的模板中访问一些 Flask 默认内置的函数和对象

config

你可以从模板中直接访问Flask当前的config对象:

    <p>{{ config.ENV }}</p><p>{{ config.DEBUG }}</p>
request

就是flask中代表当前请求的request对象:

    <p>{{ request.url }}</p><p>{{ request.path }}</p><p>{{ request.method }}</p>
session

为Flask的session对象,显示session数据

{{session.new}}
False
g变量

在视图函数中设置g变量的 name 属性的值,然后在模板中直接可以取出

{{ g.name }}
url_for()

url_for会根据传入的路由器函数名,返回该路由对应的URL,在模板中始终使用url_for()就可以安全的修改路由绑定的URL,则不比担心模板中渲染出错的链接:

{{url_for('home')}}

如果我们定义的路由URL是带有参数的,则可以把它们作为关键字参数传入url_for(),Flask会把他们填充进最终生成的URL中:

{{ url_for('index', id=1)}}
/index/1      {#  /index/<int:id> id被声明成路由参数 #}
/index?id=1   {#  /index          id被声明成路由参数 #}

课堂代码:

主程序 manage.py:

from flask import Flask, render_template,gapp = Flask(__name__, template_folder="templates")@app.route("/")
def index():g.name = "xiaohei"title = "我的flask"data_list = ["a", "b", "c"]data_dict = {"name": "xiaoming","id": 100,}user_list = [{"id":1, "name": "xiaoming", "age":16},{"id":2, "name": "xiaoming", "age":16},{"id":3, "name": "xiaoming", "age":16},]return render_template("index.html", **locals())@app.route("/user/<int:uid>")
def user(uid):print(uid)return f"uid={uid}"if __name__ == '__main__':app.run(host="0.0.0.0", port=5000, debug=True)

模板 templates/index.html:

<!doctype html>
<html lang="en">
<head><meta charset="UTF-8"><title>{{ title }}</title>
</head>
<body>
{#    <h1>{{ title }}!!</h1>#}
{#    <p>{{ data_list }}</p>#}
{#    <p>{{ data_list.1 }}</p>#}<p>{{ data_list[-1]}}</p><p>{{ data_list | last }}</p><p>{{ data_list | first }}</p><p>{{ data_dict }}</p><p>{{ data_dict.name }}</p><p>{{ user_list.0 }}</p>
{#    <p>{{ user_list.0.name }}</p>#}<p>{{ config.ENV }}</p><p>{{ config.DEBUG }}</p><p>{{ request.url }}</p><p>{{ request.path }}</p><p>{{ request.method }}</p><p>{{ session.new }}</p><p>{{ g.name }}</p><p>{{ url_for("user", uid=3) }}</p>    {# /user/3 #}</body>
</html>

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com