• Python学习十二:Flask框架


    一、Flask 简介

    Flask 依赖两个外部库:WerkZeug 和 Jinja2。WerkZeug 是一个WSGI(在web应用和多种服务器之间的标准Python 接口)工具集。Jinja2负责渲染模板。所以在安装Flask之前,需要安装这两个外部库,而最简单的方法就是使用 Virtualenv 创建虚拟环境

    1.1 安装虚拟环境

    1.1.1 安装Virtualenv

    pip install virtualenv 
    
    • 1

    检验

    virtualenv --version
    
    • 1

    1.1.2 创建虚拟环境

    下一步就是使用Virtualenv 命令在当前文件夹创建Python虚拟环境。创建虚拟环境之后当前文件夹会出现一个子文件夹,名字就是下述命令中指定的参数

    virtualenv venv
    
    • 1

    在这里插入图片描述
    在这里插入图片描述

    1.1.3 激活虚拟环境

    venv\Scripts\activate
    
    • 1

    1.2 安装Flask

    pip install flask
    
    • 1

    安装校验

    pip list --format columns
    
    
    • 1
    • 2

    在这里插入图片描述

    1.3 第一个Flask

    from flask import Flask
    app = Flask(__name__)
    
    @app.route('/')
    def hello_world():
        return 'Hello World!'
    
    if __name__ == '__main__':
        app.run(debug=True)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    在这里插入图片描述
    (1)首先我们导入了Flask类。这个类的实例将会是我们的WSGI应用程序
    (2)接下来,我们创建了一个该类的实例,第一个参数是应用模块或者包名的名称。如果你还用单一的模块,比如本例,你应该使用__name__,因为模块的名称将会因其作为一个单独的应用模块启动还是作为模块导入而有不同(也是__main_或者实际的导入名)。这是必须得,这样Flask才知道到哪儿去模板,静态文件等。详情见Flask的文档。
    (3)然后,我们使用route()装饰器告诉Flask什么样的URL能触发我们的函数
    (4)这个函数的名字也在生成URL时被特定的函数采用,这个函数返回我们想要显示在用户浏览器中的信息
    (5)最后我们使用run()函数来让应用运行在本地的服务器上面。其中if__name __=='__main__':确保服务器只会在该脚本被Python解释器直接执行的时候才会运行,而不是作为模板导入的时候

    二、Flask基础

    2.1 开启调试模式

    虽然run()方法使用与启动本地的开发服务,但是用户没每次修改代码后需要手动的重启服务,这样并不优雅,而Flask可以做到更好。如果你启用了调试支持,服务器会在代码修改后自动重新载入,并且在发生错误的时候提供一个相当可用的调试器 相当于Java的热部署
    使用方法,直接在代码中添加

     app.run(debug=True)
     或者
     app.debug=True
     app.run()
    
    
    • 1
    • 2
    • 3
    • 4
    • 5

    2.2 路由

    处理URL和函数之间的关系的程序称之为路由

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

    Hello World!

    '
    • 1
    • 2
    • 3
    • 4

    在这里插入图片描述
    修饰器是Python语言的标准特性,可以使用不同的方法修改函数的行为。惯常用法是使用修饰器把函数注册为事件的处理程序

    2.2.1 变量规则

    要给URL添加变量部分,你可以把这些特殊的字段编辑为,这个部分将会作为命名参数传递到你的函数。规格可以使用converter:variable_name指定一个可选的转化器

    from flask import Flask
    app = Flask(__name__)
    
    @app.route('/')
    def hello_world():
        return 'Hello World!'
    
    @app.route('/user/')
    def show_user_profile(username):
        # 显示该用户名的用户信息
        return 'User %s' % username
    
    @app.route('/post/')
    def show_post(post_id):
        # 根据ID显示文章,ID是整型数据
        return 'Post %d' % post_id
    
    if __name__ == '__main__':
        app.run(debug=True)
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • int:接收整数
    • float:同int,但是接受的是浮点数
    • path:和默认的相似,但是也接受斜线

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    2.2.2 构造URL

    Flask能够匹配URL,而且还可以用url_for()来给指定的函数构造URL。它接收函数名作为第一个参数,也接受对应URL规则的变量部分的命名参数。未知变量部分会添加到URL末尾作为查询条件

    from flask import Flask , url_for
    app = Flask(__name__)
    
    @app.route('/')
    def hello_world():
        return 'Hello World!'
    
    @app.route('/user/')
    def show_user_profile(username):
        # 显示该用户名的用户信息
        return 'User %s' % username
    
    @app.route('/post/')
    def show_post(post_id):
        # 根据ID显示文章,ID是整型数据
        return 'Post %d' % post_id
    
    @app.route('/url/')
    def get_url():
        # 根据ID显示文章,ID是整型数据
        return url_for('show_post',post_id=2)
    
    if __name__ == '__main__':
        app.run(debug=True)
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    在这里插入图片描述

    2.2.3 HTTP方法

    HTTP(与web应用会话的协议)有许多的不同的构造方法访问URL方法。默认情况下,路由只回应GET请求,当时通过route()装饰器传递methods 参数可以改变这个行为。

    @app.route('/', methods=['GET', 'POST'])
    def index():
    	if request.methods=='POST':
    		pass
    	else:
    		pass
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    在这里插入图片描述

    2.3 静态文件

    url_for('static',filename='style.css'),
    # 这个文件应该存储在文件系统上的static/style.css
    
    
    • 1
    • 2
    • 3
    from flask import Flask, render_template
    
    app = Flask(__name__)
    
    @app.route('/')
    def hello_world():
        return render_template('index.html')
    
    @app.route('/user/')
    def show_user_profile(username):
        # 显示该用户名的用户信息
        return render_template('user.html', name=username)
    
    if __name__ == '__main__':
        app.run(debug=True)
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    在这里插入图片描述

    在这里插入图片描述

    2.4 蓝图

    蓝图学习
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    三、模板

    模板是一个包含响应文本的额文件,其中包含用占位变量表示的动态部分,其具体值只在请求的上下文中才能知道。使用真实值替代变量,再返回最终得到的响应字符串,这一过程称为渲染。为了渲染模板,Flask使用了一个名为Jinja2的强大模板引擎

    3.1 渲染模板

    默认情况下,Flask在程序文件夹中的templates 子文件夹中寻找模板。

    比如:

    在这里插入图片描述
    在这里插入图片描述

    在这里插入图片描述

    3.2 变量

    我们可以在模板中使用变量{{name}},这表示一个占位符,而name是变量名称;
    模板学习

    <p>从一个字典中获取一个值:{{mydict['key']}}.p>
    <p>从一个列表中获取一个值:{{mylist[3]}}.p>
    <p>从一个列表中获取一个带索引的值:{{mylist[myintvar]}}.p>
    <p>从一个对象的方法中获取一个值:{{myobj.somemethod()}}.p>
    
    • 1
    • 2
    • 3
    • 4

    可以使用过滤器修改变量,过滤器添加变量名之后,中间使用竖线分隔。

    Hello,{{name|capitalize}}
    
    
    • 1
    • 2

    Jinja2提供了许多内置过滤器,常用的过滤器如下:
    在这里插入图片描述
    在这里插入图片描述

    3.3 控制结构

    3.3.1 条件控制语句

    if…else…endif

    {% if user %}
    Hello,{{user}}
    {% else %}
    Hello Stranger
    {% endif %}
    
    • 1
    • 2
    • 3
    • 4
    • 5

    3.3.2 循环语句

    {% for comment in comments %}
    {{comment}}
    {% endfor %}
    
    • 1
    • 2
    • 3

    3.3.3 宏

    宏类似于Python代码中的函数

    {% macro render_comment(comment) %}
    {{comment}}
    {% endmacro  %}
    
    {% for comment in comments %}
    {{render_comment(comment)}}
    {% endfor %}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    3.3.4 公共代码

    需要在多处重复使用的模板代码片段可以写在独立的文件,在包含在所有的模板中,以免重复
    方法一:全部包含

    {% include 'common.html' %}
    
    • 1

    方法二:继承包含
    base.html

    
    
    {%block head%}
    {%block title%}{%endblock%}-My Application
    <%endblock%>
    
    
    <body>
    {%bolck body%}
    {%endbody%}
    </body>
    </html>
    
    
    <div class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li><li style="color: rgb(153, 153, 153);">14</li></ul></pre> 
    <p>bolck标签定义的元素可在衍生模板中修改。在本例中,我们定义了名为head、title、body的块。注意。title包含在head中。</p> 
    <p>举例衍生模板</p> 
    <pre data-index="21" class="set-code-show prettyprint"><code class="prism language-html has-numbering" onclick="mdcp.signin(event)" style="position: unset;">{% extends "base.html"}
    {%block title%}Index{%endhead%}
    {%block head%}
    {<!-- -->{supper()}}
    <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>style</span><span class="token punctuation">></span></span><span class="token style"><span class="token language-css">
    </span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>style</span><span class="token punctuation">></span></span>
    {% endblock %}
    {%bolck body%}
    <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>h1</span><span class="token punctuation">></span></span>Hello<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>h1</span><span class="token punctuation">></span></span>
    {%endbody%}
    <div class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li></ul></pre> 
    <p>extends 指令声明这个模板衍生于base,html,在extends指令之后,基模板的三个块被重新定义,模板引擎将会在其插入适当的位置,注意新定义的head块,在基模板中其内容不是空的,所以用supper()获取原来的内容</p> 
    <h2><a name="t24"></a><a id="Web_309"></a>四、Web表单</h2> 
    <ul><li>web表单是允许用户和web应用交互的基本元素,FLask自己是不会处理表单的,但是Flask-WTF扩展允许用户在flask应用中使用著名的WTForms包,这个包使得定义表单和处理表单变得简单<br> <a href="http://t.csdn.cn/WWKYG" rel="nofollow">参考</a></li></ul> 
    <h3><a name="t25"></a><a id="41__313"></a>4.1 安装</h3> 
    <pre data-index="22" class="set-code-show prettyprint"><code class="prism language-python has-numbering" onclick="mdcp.signin(event)" style="position: unset;">pip install flask<span class="token operator">-</span>wtf
    <div class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li></ul></pre> 
    <p>安装成功显示如下:<br> <img src="https://1000bd.com/contentImg/2024/04/23/ce4099aef73b8996.png" alt="在这里插入图片描述"></p> 
    <h3><a name="t26"></a><a id="42_CSRF_320"></a>4.2 CSRF的保护和验证</h3> 
    <p><a href="http://www.pythondoc.com/flask-wtf/csrf.html" rel="nofollow">官网</a></p> 
    <p>CSRF跨站请求伪造,源于WEB的隐式身份验证机制。WEB的身份验证机制虽然可以抱着一个请求时来自于某个用户的浏览器,但却无法保证该请求是用户批准发送的。</p> 
    <p>例如,用户登录受信任的网址A,在本地生成了Cookie,在Cookie没有失效的情况下去访问了危险网站B。B可能会盗用你的身份,以你的名义去发送恶意请求,邮件,盗取你的账号,设置购买商品,造成你个人隐私泄露,已经财产安全。</p> 
    <p>实际上,WTForms在渲染没一个表单都会生成一个独一无二的token,这个token将在POST请求的时候随着表单一起提交进行验证。默认情况下Flask-WTF能保护所有表单免受跨域请求伪造的攻击,恶意网站把请求发送到被攻击者已经登陆的网站就会引发CSRF攻击。为了实现CSRF保护,Flask-WTF需要程序设置加密令牌,再用加密令牌来验证表单数据的真伪。</p> 
    <p>使用方法</p> 
    <pre data-index="23" class="set-code-show prettyprint"><code class="prism language-pyhon has-numbering" onclick="mdcp.signin(event)" style="position: unset;">app = Flask(__name__)
    app.config['SECRET_KEY'] = 'abcd123'
    <div class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li></ul></pre> 
    <ul><li>app.config字典可以存储框架、扩展和程序本身的配置变量。使用标准的字典语法把配置值添加到app.config对象中</li><li>SECRET_KEY配置变量是通用密钥,可在Flask和多个扩展中使用</li></ul> 
    <h3><a name="t27"></a><a id="43__339"></a>4.3 表单类</h3> 
    <p>使用Flask-WTF时,每个表单都由一个继承自Form的类表示,这个类定义表单中的一组字段。</p> 
    <p>每个字段有用对象表示,并且字段可以附属一个或者多个校验用来验证用户输入的数据是否符合要求。</p> 
    <pre data-index="24" class="set-code-show prettyprint"><code class="prism language-python has-numbering" onclick="mdcp.signin(event)" style="position: unset;"><span class="token keyword">from</span> flask_wtf <span class="token keyword">import</span> FlaskForm
    <span class="token keyword">from</span> wtforms <span class="token keyword">import</span> StringField<span class="token punctuation">,</span> PasswordField<span class="token punctuation">,</span> SubmitField
    <span class="token keyword">from</span> wtforms<span class="token punctuation">.</span>validators <span class="token keyword">import</span> Required
    <span class="token keyword">class</span> <span class="token class-name">NameForm</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span>
        name <span class="token operator">=</span> StringField<span class="token punctuation">(</span><span class="token string">'请输入姓名'</span><span class="token punctuation">,</span> validators<span class="token operator">=</span><span class="token punctuation">[</span>Required<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
        password <span class="token operator">=</span> PasswordField<span class="token punctuation">(</span><span class="token string">'请输入密码'</span><span class="token punctuation">,</span> validators<span class="token operator">=</span><span class="token punctuation">[</span>Required<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
        submit <span class="token operator">=</span> SubmitField<span class="token punctuation">(</span><span class="token string">'Submit'</span><span class="token punctuation">)</span>
    <div class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li></ul></pre> 
    <p>这个表单中所有字段都定义为类变量,类变量的值是相应字段类型的对象<br> <img src="https://1000bd.com/contentImg/2024/04/23/4b31d04308b70448.png" alt="在这里插入图片描述"><br> 在上述代码中我们使用了三个HTML标准字段,更多参考如下:<br> <img src="https://1000bd.com/contentImg/2024/04/23/1d8c34d97b63278c.png" alt="在这里插入图片描述"><br> <img src="https://1000bd.com/contentImg/2024/04/23/aa36d8731c1e7aa8.png" alt="在这里插入图片描述"></p> 
    <h3><a name="t28"></a><a id="44_HTML_360"></a>4.4 把表单渲染成HTML</h3> 
    <p>表单字段是可调用的,在模板中渲染会生成HTML。</p> 
    <p>假设视图函数把一个NameForm实力通过参数传进form表单,在模板中可以生成一个简单的表单验证用户登录信息。</p> 
    <p>创建一个model.py文件定义一个表单类LoginForm,其中有三个属性分别是name,password和submit,具体代码如下:</p> 
    <pre data-index="25" class="set-code-hide prettyprint"><code class="prism language-python has-numbering" onclick="mdcp.signin(event)" style="position: unset;"><span class="token keyword">from</span> flask_wtf <span class="token keyword">import</span> FlaskForm
    <span class="token keyword">from</span> wtforms <span class="token keyword">import</span> StringField<span class="token punctuation">,</span> PasswordField<span class="token punctuation">,</span>SubmitField
    <span class="token keyword">from</span> wtforms<span class="token punctuation">.</span>validators <span class="token keyword">import</span> DataRequired<span class="token punctuation">,</span>Length
     
    <span class="token keyword">class</span> <span class="token class-name">LoginForm</span><span class="token punctuation">(</span>FlaskForm<span class="token punctuation">)</span><span class="token punctuation">:</span>
        <span class="token triple-quoted-string string">"""
        登录表单类
        """</span>
        name <span class="token operator">=</span> StringField<span class="token punctuation">(</span>label<span class="token operator">=</span><span class="token string">'用户名'</span><span class="token punctuation">,</span> validators<span class="token operator">=</span><span class="token punctuation">[</span>
            DataRequired<span class="token punctuation">(</span><span class="token string">"用户名不能为空"</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
            Length<span class="token punctuation">(</span><span class="token builtin">max</span><span class="token operator">=</span><span class="token number">10</span><span class="token punctuation">,</span><span class="token builtin">min</span><span class="token operator">=</span><span class="token number">3</span><span class="token punctuation">,</span>message<span class="token operator">=</span><span class="token string">"用户名长度必须大于3且小于8"</span><span class="token punctuation">)</span>
        <span class="token punctuation">]</span><span class="token punctuation">)</span>
        password <span class="token operator">=</span> PasswordField<span class="token punctuation">(</span>label<span class="token operator">=</span><span class="token string">'密码'</span><span class="token punctuation">,</span> validators<span class="token operator">=</span><span class="token punctuation">[</span>
            DataRequired<span class="token punctuation">(</span><span class="token string">"密码不能为空"</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
            Length<span class="token punctuation">(</span><span class="token builtin">max</span><span class="token operator">=</span><span class="token number">10</span><span class="token punctuation">,</span> <span class="token builtin">min</span><span class="token operator">=</span><span class="token number">6</span><span class="token punctuation">,</span> message<span class="token operator">=</span><span class="token string">"用户名长度必须大于6且小于10"</span><span class="token punctuation">)</span>
        <span class="token punctuation">]</span><span class="token punctuation">)</span>
        submit <span class="token operator">=</span> SubmitField<span class="token punctuation">(</span>label<span class="token operator">=</span><span class="token string">"提交"</span><span class="token punctuation">)</span>
    <div class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}"></div></code><div class="hide-preCode-box"><span class="hide-preCode-bt" data-report-view="{"spm":"1001.2101.3001.7365"}"><img class="look-more-preCode contentImg-no-view" src="https://1000bd.com/contentImg/2022/06/27/191644837.png" alt="" title=""></span></div><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li><li style="color: rgb(153, 153, 153);">14</li><li style="color: rgb(153, 153, 153);">15</li><li style="color: rgb(153, 153, 153);">16</li><li style="color: rgb(153, 153, 153);">17</li></ul></pre> 
    <p>在文件中分别创建首页视图index()函数和登录页视图login()函数。引入我们刚才创建的model.py文件并在login()视图函数中对用户登陆进行验证,验证通过则跳转至首页,否则提示错误</p> 
    <pre data-index="26" class="set-code-hide prettyprint"><code class="prism language-python has-numbering" onclick="mdcp.signin(event)" style="position: unset;"><span class="token keyword">from</span> flask <span class="token keyword">import</span> Flask <span class="token punctuation">,</span>url_for<span class="token punctuation">,</span>redirect<span class="token punctuation">,</span> render_template
    <span class="token keyword">from</span> models <span class="token keyword">import</span> LoginForm
     
    app <span class="token operator">=</span> Flask<span class="token punctuation">(</span>__name__<span class="token punctuation">)</span>
    app<span class="token punctuation">.</span>config<span class="token punctuation">[</span><span class="token string">'SECRET_KEY'</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token string">'mrsoft'</span>
     
     
    <span class="token decorator annotation punctuation">@app<span class="token punctuation">.</span>route</span><span class="token punctuation">(</span><span class="token string">'/login'</span><span class="token punctuation">,</span> methods<span class="token operator">=</span><span class="token punctuation">[</span><span class="token string">'GET'</span><span class="token punctuation">,</span> <span class="token string">'POST'</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
    <span class="token keyword">def</span> <span class="token function">login</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span>
        <span class="token triple-quoted-string string">"""
        登录页面
        """</span>
        form <span class="token operator">=</span> LoginForm<span class="token punctuation">(</span><span class="token punctuation">)</span>
        <span class="token keyword">if</span> form<span class="token punctuation">.</span>validate_on_submit<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span>
            username <span class="token operator">=</span> form<span class="token punctuation">.</span>name<span class="token punctuation">.</span>data
            password <span class="token operator">=</span> form<span class="token punctuation">.</span>password<span class="token punctuation">.</span>data
            <span class="token keyword">if</span> username<span class="token operator">==</span> <span class="token string">"admin"</span> <span class="token keyword">and</span> password <span class="token operator">==</span> <span class="token string">"abcd1234"</span><span class="token punctuation">:</span>
                <span class="token keyword">return</span> redirect<span class="token punctuation">(</span>url_for<span class="token punctuation">(</span><span class="token string">'index'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
        <span class="token keyword">return</span> render_template<span class="token punctuation">(</span><span class="token string">'login.html'</span><span class="token punctuation">,</span>form<span class="token operator">=</span>form<span class="token punctuation">)</span>
     
    <span class="token decorator annotation punctuation">@app<span class="token punctuation">.</span>route</span><span class="token punctuation">(</span><span class="token string">'/'</span><span class="token punctuation">)</span>
    <span class="token keyword">def</span> <span class="token function">index</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span>
        <span class="token triple-quoted-string string">"""
        首页
        """</span>
        name <span class="token operator">=</span> <span class="token string">"班德尔城"</span>
        message <span class="token operator">=</span> <span class="token triple-quoted-string string">"""
            约德尔人的故乡究竟在何处?对于这个问题人们众说纷纭,不过有一些凡人声称自己穿过了无形的传送门,进入了超越物质领域的奇异魔法世界。他们都描述了一个魔法奔放的地方,鲁莽蛮横的人会被无数的奇观带入歧途,最后迷失在梦境中,永远无法返回……
    在班德尔城,任何约德尔人以外的种族都会感到自己的全部感官得到了强化。城中所见无不色彩斑斓,食物与水的味道让人经年沉醉——只要尝过一次,就终身难忘。这里日光溶溶,春水不休,每一株植物都会结出累累硕果。或许这些描述中有一部分属实,或许全都是假的——因为没有任何两个讲述者能够对所见所闻达成一致。
    只有一件事可以肯定,那就是班德尔城和里面的居民都具有某种超脱时间的属性,这或许可以解释为什么从那里回来的凡人全都像是一夜苍老了许多年岁,更多人则根本是一去不复返。
        """</span>
        <span class="token keyword">return</span> render_template<span class="token punctuation">(</span><span class="token string">"index.html"</span><span class="token punctuation">,</span>name<span class="token operator">=</span>name<span class="token punctuation">,</span>message<span class="token operator">=</span>message<span class="token punctuation">)</span>
     
    <span class="token keyword">if</span> __name__ <span class="token operator">==</span> <span class="token string">'__main__'</span><span class="token punctuation">:</span>
        app<span class="token punctuation">.</span>run<span class="token punctuation">(</span>debug<span class="token operator">=</span><span class="token boolean">True</span><span class="token punctuation">,</span>
                port<span class="token operator">=</span><span class="token number">8000</span><span class="token punctuation">)</span>
    
    <div class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}"></div></code><div class="hide-preCode-box"><span class="hide-preCode-bt" data-report-view="{"spm":"1001.2101.3001.7365"}"><img class="look-more-preCode contentImg-no-view" src="https://1000bd.com/contentImg/2022/06/27/191644837.png" alt="" title=""></span></div><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li><li style="color: rgb(153, 153, 153);">14</li><li style="color: rgb(153, 153, 153);">15</li><li style="color: rgb(153, 153, 153);">16</li><li style="color: rgb(153, 153, 153);">17</li><li style="color: rgb(153, 153, 153);">18</li><li style="color: rgb(153, 153, 153);">19</li><li style="color: rgb(153, 153, 153);">20</li><li style="color: rgb(153, 153, 153);">21</li><li style="color: rgb(153, 153, 153);">22</li><li style="color: rgb(153, 153, 153);">23</li><li style="color: rgb(153, 153, 153);">24</li><li style="color: rgb(153, 153, 153);">25</li><li style="color: rgb(153, 153, 153);">26</li><li style="color: rgb(153, 153, 153);">27</li><li style="color: rgb(153, 153, 153);">28</li><li style="color: rgb(153, 153, 153);">29</li><li style="color: rgb(153, 153, 153);">30</li><li style="color: rgb(153, 153, 153);">31</li><li style="color: rgb(153, 153, 153);">32</li><li style="color: rgb(153, 153, 153);">33</li><li style="color: rgb(153, 153, 153);">34</li><li style="color: rgb(153, 153, 153);">35</li><li style="color: rgb(153, 153, 153);">36</li><li style="color: rgb(153, 153, 153);">37</li></ul></pre> 
    <p>渲染login.html和index.html如下:</p> 
    <pre data-index="27" class="set-code-hide prettyprint"><code class="prism language-python has-numbering" onclick="mdcp.signin(event)" style="position: unset;">
    <span class="token operator"><</span>div <span class="token keyword">class</span><span class="token operator">=</span><span class="token string">"jumbotron"</span><span class="token operator">></span>
      <span class="token operator"><</span>form action<span class="token operator">=</span><span class="token string">""</span> method<span class="token operator">=</span><span class="token string">"post"</span><span class="token operator">></span>
          <span class="token operator"><</span>div <span class="token keyword">class</span><span class="token operator">=</span><span class="token string">"form-group"</span><span class="token operator">></span>
          <span class="token punctuation">{<!-- --></span><span class="token punctuation">{<!-- --></span> form<span class="token punctuation">.</span>name<span class="token punctuation">.</span>label <span class="token punctuation">}</span><span class="token punctuation">}</span>
          <span class="token punctuation">{<!-- --></span><span class="token punctuation">{<!-- --></span> form<span class="token punctuation">.</span>name<span class="token punctuation">(</span><span class="token keyword">class</span><span class="token operator">=</span><span class="token string">"form-control"</span><span class="token punctuation">)</span><span class="token punctuation">}</span><span class="token punctuation">}</span>
          <span class="token punctuation">{<!-- --></span><span class="token operator">%</span> <span class="token keyword">for</span> err <span class="token keyword">in</span> form<span class="token punctuation">.</span>name<span class="token punctuation">.</span>errors <span class="token operator">%</span><span class="token punctuation">}</span>
              <span class="token operator"><</span>p style<span class="token operator">=</span><span class="token string">"color: red"</span><span class="token operator">></span><span class="token punctuation">{<!-- --></span><span class="token punctuation">{<!-- --></span> err <span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token operator"><</span><span class="token operator">/</span>p<span class="token operator">></span>
          <span class="token punctuation">{<!-- --></span><span class="token operator">%</span> endfor <span class="token operator">%</span><span class="token punctuation">}</span>
          <span class="token operator"><</span><span class="token operator">/</span>div<span class="token operator">></span>
          <span class="token operator"><</span>div <span class="token keyword">class</span><span class="token operator">=</span><span class="token string">"form-group"</span><span class="token operator">></span>
          <span class="token punctuation">{<!-- --></span><span class="token punctuation">{<!-- --></span> form<span class="token punctuation">.</span>password<span class="token punctuation">.</span>label <span class="token punctuation">}</span><span class="token punctuation">}</span>
          <span class="token punctuation">{<!-- --></span><span class="token punctuation">{<!-- --></span> form<span class="token punctuation">.</span>password<span class="token punctuation">(</span><span class="token keyword">class</span><span class="token operator">=</span><span class="token string">"form-control"</span><span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">}</span>
          <span class="token punctuation">{<!-- --></span><span class="token operator">%</span> <span class="token keyword">for</span> err <span class="token keyword">in</span> form<span class="token punctuation">.</span>password<span class="token punctuation">.</span>errors <span class="token operator">%</span><span class="token punctuation">}</span>
             <span class="token operator"><</span>p style<span class="token operator">=</span><span class="token string">"color: red"</span><span class="token operator">></span><span class="token punctuation">{<!-- --></span><span class="token punctuation">{<!-- --></span> err <span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token operator"><</span><span class="token operator">/</span>p<span class="token operator">></span>
          <span class="token punctuation">{<!-- --></span><span class="token operator">%</span> endfor <span class="token operator">%</span><span class="token punctuation">}</span>
          <span class="token operator"><</span><span class="token operator">/</span>div<span class="token operator">></span>
          <span class="token punctuation">{<!-- --></span><span class="token punctuation">{<!-- --></span> form<span class="token punctuation">.</span>csrf_token <span class="token punctuation">}</span><span class="token punctuation">}</span>
          <span class="token punctuation">{<!-- --></span><span class="token punctuation">{<!-- --></span> form<span class="token punctuation">.</span>submit<span class="token punctuation">(</span><span class="token keyword">class</span><span class="token operator">=</span><span class="token string">"btn btn-primary"</span><span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">}</span>
      <span class="token operator"><</span><span class="token operator">/</span>form<span class="token operator">></span>
    <span class="token operator"><</span><span class="token operator">/</span>div<span class="token operator">></span>
    <div class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}"></div></code><div class="hide-preCode-box"><span class="hide-preCode-bt" data-report-view="{"spm":"1001.2101.3001.7365"}"><img class="look-more-preCode contentImg-no-view" src="https://1000bd.com/contentImg/2022/06/27/191644837.png" alt="" title=""></span></div><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li><li style="color: rgb(153, 153, 153);">14</li><li style="color: rgb(153, 153, 153);">15</li><li style="color: rgb(153, 153, 153);">16</li><li style="color: rgb(153, 153, 153);">17</li><li style="color: rgb(153, 153, 153);">18</li><li style="color: rgb(153, 153, 153);">19</li><li style="color: rgb(153, 153, 153);">20</li><li style="color: rgb(153, 153, 153);">21</li></ul></pre> 
    <pre data-index="28" class="set-code-show prettyprint"><code class="prism language-python has-numbering" onclick="mdcp.signin(event)" style="position: unset;">
    <span class="token operator"><</span>div <span class="token keyword">class</span><span class="token operator">=</span><span class="token string">"jumbotron"</span><span class="token operator">></span>
      <span class="token operator"><</span>h1 <span class="token keyword">class</span><span class="token operator">=</span><span class="token string">"display-3"</span><span class="token operator">></span>欢迎来到<span class="token punctuation">{<!-- --></span><span class="token punctuation">{<!-- --></span>name<span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token operator"><</span><span class="token operator">/</span>h1<span class="token operator">></span>
      <span class="token operator"><</span>p <span class="token operator">></span>
          <span class="token punctuation">{<!-- --></span><span class="token punctuation">{<!-- --></span>message<span class="token punctuation">}</span><span class="token punctuation">}</span>
      <span class="token operator"><</span><span class="token operator">/</span>p<span class="token operator">></span>
      <span class="token operator"><</span>hr <span class="token keyword">class</span><span class="token operator">=</span><span class="token string">"my-4"</span><span class="token operator">></span>
      <span class="token operator"><</span>p<span class="token operator">></span>
        <span class="token operator"><</span>a <span class="token keyword">class</span><span class="token operator">=</span><span class="token string">"btn btn-primary btn-lg"</span> href<span class="token operator">=</span><span class="token string">"#"</span> role<span class="token operator">=</span><span class="token string">"button"</span><span class="token operator">></span>了解更多<span class="token operator"><</span><span class="token operator">/</span>a<span class="token operator">></span>
      <span class="token operator"><</span><span class="token operator">/</span>p<span class="token operator">></span>
    <span class="token operator"><</span><span class="token operator">/</span>div<span class="token operator">></span>
    <div class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li></ul></pre> 
    <p>当我们运行run.py函数,浏览器输入</p> 
    <p>http://127.0.0.1:5000/login</p> 
    <p><img src="https://1000bd.com/contentImg/2024/04/23/cf37b0e784c421ab.png" alt="在这里插入图片描述"><br> 如果用户没有填入值就直接提交,DataRequired就会捕获这个异常</p> 
    <p><img src="https://1000bd.com/contentImg/2024/04/23/9f3fe3984309a2f6.png" alt="在这里插入图片描述"><br> 如果用户密码长度不满足要求,length()函数就会捕获这个异常<br> <img src="https://1000bd.com/contentImg/2024/04/23/aa04f4dae9392bf6.png" alt="在这里插入图片描述"><br> 密码输入无误,则会成功跳转至首页<br> <img src="https://1000bd.com/contentImg/2024/04/23/08626514bf29c5e8.png" alt="在这里插入图片描述"></p>
                    </div>
                        </div>
                    </li>
    
                    <li class="list-group-item ul-li">
    
                        <b>相关阅读:</b><br>
                        <nobr>
    <a href="/Article/Index/1442972">如何做一个能用的 JAVA 的 Websocket 聊天室?</a>                            <br />
    <a href="/Article/Index/909783">SpringBoot入门</a>                            <br />
    <a href="/Article/Index/1282306">element-ui和element-plus的自定义列表格用法</a>                            <br />
    <a href="/Article/Index/1371959">ardupilot开发 --- External LEDs篇</a>                            <br />
    <a href="/Article/Index/1397161">notes_jupyter_notebook</a>                            <br />
    <a href="/Article/Index/892904">c++学习笔记3_函数模板的使用并实现自己定义的队列</a>                            <br />
    <a href="/Article/Index/1200320">pytorch模型网页部署——Flask</a>                            <br />
    <a href="/Article/Index/890899">LeetCode_二分搜索_中等_540.有序数组中的单一元素</a>                            <br />
    <a href="/Article/Index/1289947">Convai:让虚拟游戏角色更智能的对话AI人工智能平台</a>                            <br />
    <a href="/Article/Index/1738612">32.哀家要长脑子了!</a>                            <br />
                        </nobr>
                    </li>
                    <li class="list-group-item from-a mb-2">
                        原文地址:https://blog.csdn.net/huiguo_/article/details/127831803
                    </li>
    
                </ul>
            </div>
    
            <div class="col-lg-4 col-sm-12">
                <ul class="list-group" style="word-break:break-all;">
                    <li class="list-group-item ul-li-bg" aria-current="true">
                        最新文章
                    </li>
                    <li class="list-group-item ul-li">
                        <nobr>
    <a href="/Article/Index/1484446">攻防演习之三天拿下官网站群</a>                            <br />
    <a href="/Article/Index/1515268">数据安全治理学习——前期安全规划和安全管理体系建设</a>                            <br />
    <a href="/Article/Index/1759065">企业安全 | 企业内一次钓鱼演练准备过程</a>                            <br />
    <a href="/Article/Index/1485036">内网渗透测试 | Kerberos协议及其部分攻击手法</a>                            <br />
    <a href="/Article/Index/1877332">0day的产生 | 不懂代码的"代码审计"</a>                            <br />
    <a href="/Article/Index/1887576">安装scrcpy-client模块av模块异常,环境问题解决方案</a>                            <br />
    <a href="/Article/Index/1887578">leetcode hot100【LeetCode 279. 完全平方数】java实现</a>                            <br />
    <a href="/Article/Index/1887512">OpenWrt下安装Mosquitto</a>                            <br />
    <a href="/Article/Index/1887520">AnatoMask论文汇总</a>                            <br />
    <a href="/Article/Index/1887496">【AI日记】24.11.01 LangChain、openai api和github copilot</a>                            <br />
                        </nobr>
                    </li>
                </ul>
    
                <ul class="list-group pt-2" style="word-break:break-all;">
                    <li class="list-group-item ul-li-bg" aria-current="true">
                        热门文章
                    </li>
                    <li class="list-group-item ul-li">
                        <nobr>
    <a href="/Article/Index/888177">十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!</a>                            <br />
    <a href="/Article/Index/797680">奉劝各位学弟学妹们,该打造你的技术影响力了!</a>                            <br />
    <a href="/Article/Index/888183">五年了,我在 CSDN 的两个一百万。</a>                            <br />
    <a href="/Article/Index/888179">Java俄罗斯方块,老程序员花了一个周末,连接中学年代!</a>                            <br />
    <a href="/Article/Index/797730">面试官都震惊,你这网络基础可以啊!</a>                            <br />
    <a href="/Article/Index/797725">你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法</a>                            <br />
    <a href="/Article/Index/797702">心情不好的时候,用 Python 画棵樱花树送给自己吧</a>                            <br />
    <a href="/Article/Index/797709">通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!</a>                            <br />
    <a href="/Article/Index/797716">13 万字 C 语言从入门到精通保姆级教程2021 年版</a>                            <br />
    <a href="/Article/Index/888192">10行代码集2000张美女图,Python爬虫120例,再上征途</a>                            <br />
                        </nobr>
                    </li>
                </ul>
    
            </div>
        </div>
    </div>
    <!-- 主体 -->
    
    
        <!--body结束-->
        <!--这里是footer模板-->
        
        <!--footer-->
    <nav class="navbar navbar-inverse navbar-fixed-bottom">
        <div class="container">
            <div class="row">
                <div class="col-md-12">
                    <div class="text-muted center foot-height">
                        Copyright © 2022 侵权请联系<a href="mailto:2656653265@qq.com">2656653265@qq.com</a>   
                        <a href="https://beian.miit.gov.cn/" target="_blank">京ICP备2022015340号-1</a>
                    </div>
                    <div style="width:300px;margin:0 auto; padding:0px 5px;">
                        <a href="/regex.html">正则表达式工具</a>
                        <a href="/cron.html">cron表达式工具</a>
                        <a href="/pwdcreator.html">密码生成工具</a>
                    </div>
                    <div style="width:300px;margin:0 auto; padding:5px 0;">
                        <a target="_blank" href="http://www.beian.gov.cn/portal/registerSystemInfo?recordcode=11010502049817" style="display:inline-block;text-decoration:none;height:20px;line-height:20px;">
                        <img src="" style="float:left;" /><p style="float:left;height:20px;line-height:20px;margin: 0px 0px 0px 5px; color:#939393;">京公网安备 11010502049817号</p></a>
                    </div>
                </div>
            </div>
        </div>
      
    </nav>
    <!--footer-->
    
        <!--footer模板结束-->
    
        <script src="/js/plugins/jquery/jquery.js"></script>
        <script src="/js/bootstrap.min.js"></script>
    
        <!--这里是scripts模板-->
        
    
        
     
    
    
        <!--scripts模板结束-->
    
    </body>
    </html>