Flask框架 完整实战案例 附代码解读 【3】

news2024/11/15 4:23:35

        Flask 是一个轻量级的可定制框架,使用Python语言编写,较其他同类型框架更为灵活、轻便、安全且容易上手。

        前面已经写过项目从新建运行安装到测试部署的全流程,其中有写Flask框架从新建到部署全流程,但是只有部分代码。本篇主要是实战案例项目的代码运行全流程说明,自己总结的方便查看,也欢迎正在学习的宝子参考,如果有不对的地方,请评论区留言或者私信我,感谢。

目录

一、新建项目以及虚拟环境

二、项目案例代码部分

1.应用工厂

1.1 运行应用

2.数据库

2.1 与数据库建立连接

2.2 创建数据表 

2.3 在应用中注册

2.4 初始化数据库文件

3.蓝图和视图

3.1创建蓝图

3.2新建视图 注册用户

4.模板 

4.1基础布局

4.2 注册模板

4.3 注册一个用户


一、新建项目以及虚拟环境

这里把新建项目以及虚拟环境在写一遍:

这里可以用命令行新建、也可以直接右键新建项目。然后命令行打开文件夹,这里只是举例子,本次项目的项目名称是 flask-tutorial 文件夹。

py -3 -m venv venv    # 创建虚拟环境
venv\Scripts\activate # 激活虚拟环境

新建的项目要新建虚拟环境然后激活虚拟环境,对于已经新建过虚拟环境的直接激活虚拟环境就可以了。

后面下载框架或者项目中需要的包运行应用都是在虚拟环境下进行的。

二、项目案例代码部分

        一个 Flask应用是一个Flask 类的实例,我们在代码的最开始创建一个全局 Flask 实例如何创建全局实例呢?可以在一个函数内部创建一个flask实例,然后把这个应用返回,这个函数被称为应用工厂,因为所有应用的相关配置、注册登录和其他设置都是在这一个函数完成的。

1.应用工厂

        创建一个 flaskr 文件夹,然后新建 __init__.py文件。应用里面的 SECRET_KEY 变量也就是我们上一篇关于项目打包部署的时候生成密钥的值。

        SECRET_KEY 是被 Flask 和扩展用于保证数据安全的。在开发过程中, 为了方便可以设置为 'dev' ,但是在发布的时候应当使用一个随机值来 重载它。

# flaskr/__init__.py 文件代码部分
import os
from flask import Flask

def create_app(test_config=None):
    # 创建一个应用实例app
    app = Flask(__name__, instance_relative_config=True)
    app.config.from_mapping(
        SECRET_KEY='dev',
        DATABASE=os.path.join(app.instance_path, 'flaskr.sqlite'),
    )

    if test_config is None:
        # load the instance config, if it exists, when not testing
        app.config.from_pyfile('config.py', silent=True)
    else:
        # load the test config if passed in
        app.config.from_mapping(test_config)

    # ensure the instance folder exists
    try:
        os.makedirs(app.instance_path)
    except OSError:
        pass

    # a simple page that says hello
    @app.route('/hello')
    def hello():
        return 'Hello, World!'

    return app   #返回应用
1.1 运行应用

前面我们已经设置了应用工厂,所以这里我们应用模块就是flaskr,在设置开发模式,然后运行应用。事实上,后面我们在加入其他代码包括设置或者功能模块也是这样运行的,因为都是在工厂模式里面调用的。

set FLASK_APP=flaskr  #设置应用在哪
> set FLASK_ENV=development  #设置开发模式
> flask run  #运行应用
2.数据库

 Python 内置了 SQLite 数据库支持,项目也是使SQLite来存储数据的,相应的模块为sqlite3.

        使用 SQLite 的便利性在于不需要单独配置一个数据库服务器,并且 Python 提供了 内置支持。小应用没有问题,但是大应用可能就需要考虑换成别的数据库了。

2.1 与数据库建立连接

新建flaskr/db.py文件:

# flaskr/db.py 文件代码

import sqlite3
import click
from flask import current_app, g
from flask.cli import with_appcontext

def get_db():
    if 'db' not in g:
        #建立一个数据库连接 该连接指向配置中的 DATABASE 指定的文件
        g.db = sqlite3.connect(
            current_app.config['DATABASE'],
            detect_types=sqlite3.PARSE_DECLTYPES
        )
        #告诉连接返回类似于字典的行,这样可以通过列名称来操作 数据
        g.db.row_factory = sqlite3.Row

    return g.db


def close_db(e=None):
    db = g.pop('db', None)

    # 如果连接已建立就关闭连接
    if db is not None:
        db.close()

在上面的代码中 是一个特殊对象,独立于每一个请求,用于存储请求过程中可能多个函数都会用到的数据,把连接储存起来可以多次使用。

 current_app 是另一个特殊对象,该对象指向处理请求的 Flask 应用,就是使用这个特殊对象,get_db 函数才会被调用。

2.2 创建数据表 

现在要创建一个sql文件,用于生成应用中用到的数据表的sql语句,我们用数据表user来存储用户信息,用数据表名posts来存储博客数据。

新建文件flaskr/schema.sql :

DROP TABLE IF EXISTS user;
DROP TABLE IF EXISTS post;

CREATE TABLE user (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  username TEXT UNIQUE NOT NULL,
  password TEXT NOT NULL
);

CREATE TABLE post (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  author_id INTEGER NOT NULL,
  created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
  title TEXT NOT NULL,
  body TEXT NOT NULL,
  FOREIGN KEY (author_id) REFERENCES user (id)
);

sql文件写好了,我们需要调用这个文件执行sql语句,前面我们已经db.py文件中已经连接数据,我们继续在db.py文件中写入python函数用来执行sql文件:

flaskr/db.py文件中新增执行sql文件的函数:

def init_db():
    db = get_db()

    with current_app.open_resource('schema.sql') as f:  #打开sql文件
        db.executescript(f.read().decode('utf8')) #执行sql文件命令

# #定义一个名为 init-db 命令行,它调用 init_db 函数,并为用户显示一个成功的消息
@click.command('init-db') 
@with_appcontext
def init_db_command():
    """Clear the existing data and create new tables."""
    init_db()
    click.echo('Initialized the database.')
2.3 在应用中注册

close_db 和 init_db_command 函数需要在应用实例中注册,否则无法使用,我们写一个函数,把应用作为参数,在函数中进行注册。

flaskr/db.py新增代码:

def init_app(app):
    app.teardown_appcontext(close_db) #告诉 Flask 在返回响应后进行清理的时候调用此函数
    app.cli.add_command(init_db_command) #添加一个新的 可以与 flask 一起工作的命令。

然后在工厂中调用init_app()函数.在工厂中导入并调用这个函数。在工厂函数中把新的代码放到 函数的尾部,返回应用代码的前面。

flaskr/__init__.py文件代码新增:

def create_app():
    app = ...
    # existing code omitted

    from . import db
    db.init_app(app)

    return app
2.4 初始化数据库文件

我们现在已经把应用在函数中进行注册了,现在可以运行应用了,还是和上面一样设置下应用模块然后flask run 运行:

set FLASK_APP=flaskr  #设置应用在哪
set FLASK_ENV=development  #设置开发模式
flask run  #运行应用
flask init-db
#Initialized the database.

现在会有一个 flaskr.sqlite 文件出现在项目所在文件夹的 instance 文件夹 中。

3.蓝图和视图

试图和蓝图不一样,简单的讲视图是响应请求的函数,返回数据。Blueprint蓝图是组织一组相关视图和其他代码的方式。把视图和代码注册到蓝图,然后在工厂函数中 把蓝图注册到应用。

3.1创建蓝图

Flaskr 有两个蓝图,一个用于认证功能,另一个用于博客帖子管理。每个蓝图的代码 都在一个单独的模块中。使用博客首先需要认证,因此我们先写认证蓝图。

新建文件flaskr/auth.py 代码如下:

import functools

from flask import (
    Blueprint, flash, g, redirect, render_template, request, session, url_for
)
from werkzeug.security import check_password_hash, generate_password_hash

from flaskr.db import get_db

bp = Blueprint('auth', __name__, url_prefix='/auth')

这里创建了一个名称为 'auth' 的 Blueprint 。和应用对象一样, 蓝图需要知道是在哪里定义的,因此把 __name__ 作为函数的第二个参数。 url_prefix 会添加到所有与该蓝图关联的 URL 前面。

使用 app.register_blueprint 导入并注册 蓝图。新的代码放在工厂函数的尾部返回应用之前。

flaskr/__init__.py文件新增代码:

def create_app():
    app = ...
    # existing code omitted

    from . import auth
    app.register_blueprint(auth.bp)

    return app

认证蓝图将包括注册新用户、登录和注销视图。

3.2新建视图 注册用户

在flaskr/auth.py文件中新增视图代码:

#bp.route关联了 URL /register 和 register 视图函数
@bp.route('/register', methods=('GET', 'POST')) 
def register():
    if request.method == 'POST':
        username = request.form['username']
        password = request.form['password']
        db = get_db()
        error = None

        if not username:
            error = 'Username is required.'
        elif not password:
            error = 'Password is required.'
        elif db.execute(
            'SELECT id FROM user WHERE username = ?', (username,)
        ).fetchone() is not None:
            error = 'User {} is already registered.'.format(username)

        if error is None:
            # db.execute使用了带有 ? 占位符 的 SQL 查询语
            db.execute(
                'INSERT INTO user (username, password) VALUES (?, ?)',
                (username, generate_password_hash(password))
            )
            db.commit()
            return redirect(url_for('auth.login'))

        flash(error)

    return render_template('auth/register.html')

占位符可以代替后面的元组参数中相应的值。使用占位符的 好处是会自动帮你转义输入值,以抵御 SQL 注入攻击 。

 fetchone() 根据查询返回一个记录行。 如果查询没有结果,则返回 None 。视图中如果查询到用户已存在则提示用户已存在,如果用户不存在就向数据插入一条用户信息的数据,然后提交数据库,跳转到登录页面。当用户最初访问视图会打开一个注册页面的表单,render_template会渲染一个包含 HTML 的模板。

后面登录、注销其实逻辑都是一样的。

4.模板 

模板文件其实就是HTML。会储存在 flaskr 包内的 templates 文件夹内。模板是包含静态数据和动态数据占位符的文件。模板使用指定的数据生成最终的文档。Flask 使用 Jinja 模板库来渲染模板。

4.1基础布局

应用中的每一个页面主体不同,但是基本布局是相同的。每个模板会 扩展 同一个 基础模板并重载相应的小节,而不是重写整个 HTML 结构。

新建flaskr/templates/base.html文件 :

<!doctype html>
<title>{% block title %}{% endblock %} - Flaskr</title>
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
<nav>
  <h1>Flaskr</h1>
  <ul>
    {% if g.user %}
      <li><span>{{ g.user['username'] }}</span>
      <li><a href="{{ url_for('auth.logout') }}">Log Out</a>
    {% else %}
      <li><a href="{{ url_for('auth.register') }}">Register</a>
      <li><a href="{{ url_for('auth.login') }}">Log In</a>
    {% endif %}
  </ul>
</nav>
<section class="content">
  <header>
    {% block header %}{% endblock %}
  </header>
  {% for message in get_flashed_messages() %}
    <div class="flash">{{ message }}</div>
  {% endfor %}
  {% block content %}{% endblock %}
</section>

在模板中 g 和 url_for() 可直接使用,g.user()显示用户状态,用户名或者注销显示注册和登录连接,url_for可用于生成视图的 URL ,而不用手动来指定。

模板中定义三个块,这些块会被其他模板重载。

  1. {% block title %} 会改变显示在浏览器标签和窗口中的标题。

  2. {% block header %} 类似于 title ,但是会改变页面的标题。

  3. {% block content %} 是每个页面的具体内容,如登录表单或者博客帖子。

其他模板直接放在 templates 文件夹内。为了更好地管理文件,属于某个蓝图 的模板会被放在与蓝图同名的文件夹内。

4.2 注册模板

flaskr/templates/auth/register.html

{% extends 'base.html' %}

{% block header %}
  <h1>{% block title %}Register{% endblock %}</h1>
{% endblock %}

{% block content %}
  <form method="post">
    <label for="username">Username</label>
    <input name="username" id="username" required>
    <label for="password">Password</label>
    <input type="password" name="password" id="password" required>
    <input type="submit" value="Register">
  </form>
{% endblock %}

{% extends 'base.html' %} 告诉 Jinja 这个模板基于基础模板,并且需要替换 相应的块。所有替换的内容必须位于 {% block %} 标签之内。

一个实用的模式是把 {% block title %} 放在 {% block header %} 内部。 这里不但可以设置 title 块,还可以把其值作为 header 块的内容, 一举两得。

静态文件 除了 CSS ,其他类型的静态文件可以是 JavaScript 函数文件或者 logo 图片。它们 都放置于 flaskr/static 文件夹中,并使用 url_for('static', filename='...') 引用。基础模板中有用到引入样式文件。

4.3 注册一个用户

现在浏览器输入http://127.0.0.1:5000/auth/register 可以注册一个用户了。请确定服务器还在运行

博客蓝图和视图逻辑都类似的。

项目代码部分完成后,然后项目可安装化和部署前面一篇项目部署全流程都总结过啦!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2099711.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

国产光耦合器在提高各行业能源效率方面的作用

随着各行业对节能解决方案的需求不断增长&#xff0c;国产光耦合器已成为降低能耗和提高整体系统效率的关键部件。这些由本地制造商开发的组件现在不仅因其成本效益而受到认可&#xff0c;而且还因其能够满足需要可靠隔离和高效电源管理的工业应用的特定需求而受到认可。 通过隔…

语义传输中单智能体语义知识库

在语义传输中涉及到的智能体包括信源数据模态、信宿智能任务以及信道传输环境。单智能体系统仅涉及一个智能体&#xff0c;该智能体独立完成感知、决策和执行任务&#xff0c;通常在不需要与其他智能体直接交互的环境中运行&#xff0c;能自主获取环境信息&#xff0c;并基于自…

PHP高效进销存管理系统智能管理库存销售与采购系统小程序源码

高效进销存管理系统 —— 智能管理&#xff0c;轻松驾驭库存、销售与采购 &#x1f525; 【开篇&#xff1a;告别繁琐&#xff0c;拥抱智能管理】 你还在为库存管理混乱、销售数据不清、采购计划难定而烦恼吗&#xff1f;是时候告别那些低效的手工账本和复杂的Excel表格了&…

传输层(TCP、UDP、RDT详解)

目录 1.无连接传输&#xff1a;UDP UDP&#xff1a;User Datagram Protocol&#xff08;用户数据报协议&#xff09; UDP&#xff1a;校验和 Internet校验和的例子 2.可靠数据传输&#xff08;Rdt&#xff09;的原理 可靠数据传输&#xff1a;问题描述 1.Rdt1.0&#xff…

【JAVA】两轮充电桩设计模式实践分享

如果说数据结构和算法是程序员构建高效代码的基石&#xff0c;那么设计模式则是打造高质量代码的“内功心法”。掌握并应用合适的设计模式&#xff0c;有助于管理项目复杂性&#xff0c;简化维护&#xff0c;并加速开发进程。 因此&#xff0c;深入理解并合理运用设计模式&…

HTTP 请求方法(method)介绍

目录 一、GET 二、POST 三、其他方法 3.1 PUT 3.2 DELETE 3.3 HEAD 3.4 OPTIONS 3.5 TRACE 3.6 CONNECT 3.7 PATCH 3.8 LINK 和 UNLINK&#xff08;扩展方法&#xff09; HTTP&#xff08;超文本传输协议&#xff09;定义了多种请求方法&#xff0c;如&#xff1a; …

opencv计算机视觉识别图像处理c++项目实战python网课程视频教程

课程名称 《OpenCV计算机视觉识别图像处理C实战课程》 课程亮点 全面覆盖&#xff1a;从基础概念到高级技术&#xff0c;涵盖OpenCV的核心功能。实战导向&#xff1a;通过具体项目实践&#xff0c;帮助学员掌握图像处理的实际应用。双语言支持&#xff1a;虽然重点是C&#x…

使用神卓互联内网穿透开发支付宝支付回调环境(Java版)

支付宝支付功能在电商网站和其他在线服务中扮演着重要角色。对于使用Java作为开发语言的应用来说&#xff0c;集成支付宝支付回调功能是必不可少的一部分。为了能够在本地开发环境中测试这一功能&#xff0c;内网穿透技术可以让我们绕过公网IP的限制。下面将介绍如何利用神卓互…

Unity教程(十三)敌人状态机

Unity开发2D类银河恶魔城游戏学习笔记 Unity教程&#xff08;零&#xff09;Unity和VS的使用相关内容 Unity教程&#xff08;一&#xff09;开始学习状态机 Unity教程&#xff08;二&#xff09;角色移动的实现 Unity教程&#xff08;三&#xff09;角色跳跃的实现 Unity教程&…

集成电路学习:什么是I/O输入输出

I/O&#xff1a;输入输出 I/O&#xff0c;全称Input/Output&#xff0c;即输入输出&#xff0c;是信息处理系统&#xff08;如计算机&#xff09;与外部世界&#xff08;可能是人类或另一信息处理系统&#xff09;之间的通信方式。具体来说&#xff0c;输入是系统接收的信号或数…

shell编程--正则表达式

正则表达式 正则表达式都被置于两个正斜杠之间&#xff1b;如/l[oO]ve/ 示例 匹配数字的脚本&#xff0c;用户输入创建账号的数量 语法&#xff1a; [[ ^[0-9]$ ]] 表示必须输入数字 #!/bin/bashwhile : do read -p "输入数字&#xff1a;" numif [[ $num ~ ^[…

springboot整合logback进行日志管理(下篇)

上一篇介绍了springboot整合logback的一些项目中用到的经验&#xff0c;本片文章继续介绍在项目中实际用到的工程经验 1、设想一下有这样一个场景&#xff1a;我想把我所有service层的日志单独打印到service.log中&#xff0c;那应该怎么做&#xff1f; 有人会说了可以配置一…

高收录高权重的采集站源码——码山侠

前端预览&#xff1a;i5i.net——码山侠点击看看 采集非常简单&#xff0c;不伪原创&#xff0c;也不处理种种外链&#xff0c;也不需要什么配图&#xff0c;而且结构也不复杂。 后台管理&#xff1a; 文章发布手动发布及编辑管理后台 采集以及伪原创类工具后台&#xff1a; …

计算机毕业设计PyHive+Hadoop深圳共享单车预测系统 共享单车数据分析可视化大屏 共享单车爬虫 共享单车数据仓库 机器学习 深度学习 PySpark

毕业设计题目基于 Hadoop 的共享单车布局规划 二、毕业设计背景 公共交通工具的“最后一公里”是城市居民出行采用公共交通出行的主要障碍&#xff0c;也是建设绿色城市、低碳城市过程中面临的主要挑战。 共享单车&#xff08;自行车&#xff09;企业通过在校园、地铁站点、公…

光储充微电网能量管理系统控制策略研究及并网分析

引言 近年来&#xff0c;我国日益重视分布式能源和微电网的发展&#xff0c;特别是光伏系统和储能技术的应用&#xff0c;这些已成为确保电力供应可靠性、促进新能源利用和减少污染的关键措施。我国新能源领域的专家对光伏储能控制系统进行了深入研究&#xff0c;强调了其应用…

【Qt】 QComboBox | QSpinBox

文章目录 QComboBox —— 下拉框QComboBox 属性核心方法核心信号QComboBox 使用 QSpinBox —— 微调框QSpinBox 属性核心信号QSpinBox 使用 QComboBox —— 下拉框 QComboBox 属性 QComboBox —— 表示下拉框 currentText ——当前选中的文本 currentindex ——当前选中的条…

STM32 ADC采样详解

Content 0x00 前言0x01 ADC配置0x02 滤波处理 0x00 前言 在单片机开发过程中&#xff0c;常常涉及到ADC的使用&#xff0c;市面上大部分便宜的传感器都是采用的ADC来获取其数据&#xff0c;如MQ-2 烟雾传感器、光敏传感器等等。 此类传感器工作原理为根据所采集到的数据变化…

Axure健康助理小程序原型图70+页,医疗类高保真高交互模板

作品概况 页面数量&#xff1a;共 70 页 源文件格式&#xff1a;限 Axure RP 9/10&#xff0c;非app软件无源码 适用领域&#xff1a;医疗健康、健康助理 作品特色 本作品为健康助理小程序的Axure原型设计图&#xff0c;属于医疗健康项目&#xff0c;设计规范内容清晰&#…

坐牢第三十三天(手搓string)

一.mystring类 #include <iostream> #include <cstring> // 引入cstring以使用memcpy using namespace std; class myString {char *str; // 记录c风格的字符串int size; // 记录字符串的实际长度int my_capacity; // 记录最大容量 public:// 无参构…

LACP链路聚合

链路聚合包含两种模式&#xff1a;手动负载均衡模式和LACP&#xff08;Link AggregationControl Protocol&#xff09;模式。 手工负载分担模式&#xff1a;Eth-Trunk的建立、成员接口的加入由手工配置&#xff0c;没有链路聚合控制协议的参与。该模式下所有活动链路都参与数…