Python web 开发 flask 实践

1、前言

前文已经介绍了很多关于 python 的算法和脚本的写法,在本文将开启python的 web 的开发,和java 类似的,对于 web 开发也需要引入框架,对于 python 的 web 开发来说常见的有 flask 和 django 两种,在本文中将要介绍的是 flask 框架,相对来说起步简单一点儿。

2、环境准备

在开发之前,需要先安装 flask 的依赖,如下所示:

pip install flask 

案例中的项目使用的环境是 python3.8, 不同于 java, python 的环境会因为依赖产生各种各样的问题,为了保证环境的一致性,需要保证依赖的版本一致。那么如何保证环境和版本的一致呢?

# 通常采用 pip freeze 生成当前环境的所有依赖
pip freeze > requirements.txt
# 采用 pip install 来安装文件中的所有依赖
pip install -r requirements.txt
# 如果只安装本项目的依赖,则需要安装 pip install pipreqs
# 通过以下命令来生成项目依赖的版本
pipreqs . --encoding=utf8 --force

3、项目结构

对于web项目开发,也可以根据 mvc 的原则来划分项目,如下图所示:

1716821008493.png

  • model 模块用来存放数据库表对应的实体
  • script 模块用来存放数据库脚本和sh 脚本
  • static 是项目的静态文件,这里使用的是前端后端不分离的模式,所以有静态模块和html末班
  • templates html 模版文件
  • web 即存放控制器的模块
  • business 存放业务模块
  • app 项目启动的入口
  • utils 即项目木启动所需要的工具类

对于 web 项目的创建,可以使用 pycharm 中的新建项目模块完成项目的创建和基础配置,也可以手工创建文件的方式来创建项目。

1716824388507.png

4、项目app

flask 的入口文件为 app.py, 基础的配置以及依赖都在其中设置。这里通常配置 web 的访问和数据库的配置信息,还有项目的启动设置。

4.1 蓝图 Blueprint

通常情况下页面访问配置为 @app.route 即可访问,但是需要将页面路由的配置设置在 app.py 中,如果业务复杂或者路由过多的情况,就不太合适。通常在开发中可以使用蓝图来处理这类问题。

# 引入蓝图
from flask import Blueprint
# 注册蓝图,设置蓝图的名称,以及路径,url_prefix即访问前缀, 类似与spring controller 类上标注的 requestmapping。Login 为蓝图的名称,要唯一。
login_blue_print = Blueprint('Login', __name__, url_prefix="/login")# 在使用蓝图时,需要使用的注解为 @login_blue_print.route 而非 app.route

1717932243771.png

4.2 数据库配置 sqlalchemy

对于数据库的配置,可以通过配置文件的方式来设置,具体的配置如下图所示:

# 配置方式
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = True
# 配置文件的方式
app.config.from_object(config)

1717944528756.png

对于数据库的操作,可以使用 pymysql 的方式来操作数据库,对于脚本来说是合适的,但是对于 web 开发来说,还是需要采用面向对象的方式,这里使用的 orm 框架是 SQLAlchemy , 对于 django 框架来说也是同样的。

1717944768099.png

数据库实体类需要集成db.Model, 在实体类中可以设置数据库的表名称,字段名称,类型,默认值,注释,主键,索引,约束键等信息。数据库采用的是下划线的命名方式,对应的实体是驼峰命名。

class User(db.Model):__tablename__ = "tb_user"id = db.Column(db.Integer, primary_key=True, autoincrement=True, comment='主键')userId = db.Column("user_id", db.String(32), default="", unique=True, comment='用户Id')username = db.Column(db.String(32), default="", comment='用户')email = db.Column(db.String(32), default="", nullable=False, comment='邮箱')cellphone = db.Column(db.String(32), default="", comment='手机号')status = db.Column(db.String(32), default="",  comment='状态')seq = db.Column(db.Integer, default="", comment='seq')createTime = db.Column("create_time", db.DateTime, default=datetime.now, comment='创建时间')updateTime = db.Column("update_time", db.DateTime, default=datetime.now, comment='更新时间')
wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==
4.3 热加载

在开发模式下,需要开启热加载的模式,方便开发的调试,通过以下的方式可以实现热加载。

1717948720300.png

5、数据库操作

数据库的操作是开展业务的核心,简单的说就是如何在 python 中实现数据的增删改查,sqlalchemy 这个 orm 框架如何实现数据的增删改查呢?

5.1 数据新增

对于数据新增的场景,需要先创建对象,然后需要将对象加入的当前会话中,并提交修改即可。

user = User()
user.username= "小明"
user.age = 34
# 单条保存
db.session.add(user)
# 多条保存
# db.session.add_all([user, user2, user3])
# 事务失败会自动回滚
db.session.commit()
5.2 数据查询

数据的查询种类比较多,具体如下所示

# 返回列表, 元素为模型对象
usr = User.query.all()
# 根据条件查询数据的数量
cnt = User.query.count()
print("cnt ", cnt)
# 根据查询第一条数据,根据年龄age和 userId 排序,默认排序为顺序排 desc
fst = User.query.order_by(User.age.asc(), User.userId.desc()).first()
print("user ", autils.trans_item(fst))
res_list = autils.trans_items(usr)
# 查询id = 10 的用户数据
us = User.query.get(10)# 等值过滤器 关键字实参设置字段值,返回查询的对象
# BaseQuery对象可以续接其他过滤器/执行器  如 all/count/first等
User.query.filter_by(id=4).all()
# 复杂过滤器,参数为比较运算/函数引用等
User.query.filter(User.id == 4).first()# 查询名字进行查询,字符串结束,开始,包含,最常用的还是 like 模糊查询
User.query.filter(User.username.endswith("李")).all()
User.query.filter(User.username.startswith("明")).all()
User.query.filter(User.username.contains("晓")).all()
User.query.filter(User.username.like("赵")).all()  # 模糊查询
# 根据名称和邮箱进行查询,且的关系
User.query.filter(and_(User.username.startswith('li'), User.email.startswith('li'))).all()
# 或的关系
User.query.filter(or_(User.age == 25, User.email.endswith("itheima.com"))).all()
# 根据id list 进行查询数据
User.query.filter(User.id.in_([1, 3, 5, 7, 9])).all()
# 查询数据 offset limit 结合使用
User.query.order_by(User.age).offset(1).limit(4).all()# 分页查询,查询第2页的数据,每页10个paginate(页码, 每页条数)
pn = User.query.paginate(page=2, per_page=10)
5.3 数据修改

对于数据的修改,需要先查询数据,然后修改完成之后进行保存即可。数据的修改有两种模式, 具体如下所示

# 1 执行查询语句, 获取目标模型对象
user = User.query.filter(User.id == 100).first()
# 2 对模型对象的属性进行赋值 (更新数据)
user.age = user.age + 1
# 3 提交会话
db.session.commit()# 这里的修改传入的是一个字典,需要修改多个需要传入多个值即可。
User.query.filter(User.id = 1).update({'age': User.age - 1})
# 提交会话
db.session.commit()
5.4 数据删除

对于数据的删除,可以先查询后删除,也可以基于过滤条件的删除,和数据修改类似,具体如下所示:

# 1 执行查询语句, 获取目标模型对象
user = User.query.filter(User.id == 100).first()
# 2 删除数据
db.session.delete(user)
# 3 提交会话
db.session.commit()# 这里可以根据多个过滤条件进行删除数据
User.query.filter(User.id = 1).delete()
# 提交会话
db.session.commit()

6、前端模块

这里使用的是前后端不分离的形式,如果使用前后端分离的方式,需要配置跨域:

from flask_cors import CORS
# 配置跨域 cors
cors = CORS(app, supports_credentials=True, resources=r'/*')

如果使用前后端不分离的方式,和 springmodel 类似,需要将参数传输到前端用于 html 的数据渲染。这里采用的是 flaskrender_template, 第一个参数是前端模版文件的名称,之后是在前端需要渲染的参数名以及参数值。

1717950216495.png

在前端渲染时,使用的方式和 jsp 类似,不过采用的是 {{}} 的方式来渲染参数,对于 for 循环和 if 条件判断也有类似的语法。

1717950143505.png

7、数据库连接池

前面讲述了如何使用 sqlalchemy 这个 orm 框架来查询数据,返回的对象需要经过转换才能返回到前端,在脚本中可以通过 dbutils.pooled_dbpymysql 进行包装来封装数据的操作。具体的操作如下所示:

import pymysql
from dbutils.pooled_db import PooledDB
# 声明数据库连接池
class DbPool(object):# 类变量数据库连接池__pool = Nonedef __init__(self, db_config):# 构造函数,创建数据库连接、游标self.coon = DbPool.get_mysql_conn(db_config)self.cur = self.coon.cursor(cursor=pymysql.cursors.DictCursor)# 数据库连接池连接@staticmethoddef get_mysql_conn(db_config):# 声明为全局变量global __poolif DbPool.__pool is None:__pool = PooledDB(creator=pymysql, mincached=1, maxcached=20, host=db_config['host'],user=db_config['user'], passwd=db_config['passwd'], db=db_config['db'],port=db_config['port'], charset=db_config['charset'])return __pool.connection()# 数据插入\更新\删除sqldef op_update(self, sql, param):print('op_insert', sql, param)insert_num = self.cur.execute(sql, param)# commit 请求 self.coon.commit()return insert_num# 数据查询def op_query(self, sql, parm):print('op_select', sql, parm)self.cur.execute(sql, parm)  # 执行sqlselect_res = self.cur.fetchall()  # 返回结果为字典return select_res# 批量更新数据def op_update_list(self, list):sum = 0try:for tuple in list:sql, parm = tupleinsert_num = self.cur.execute(sql, parm)if (insert_num == 0):self.coon.rollback()breaksum += insert_numself.coon.commit()except:print('事务回滚')self.coon.rollback()return sum# 释放资源# 释放资源def dispose(self):self.coon.close()self.cur.close()
if __name__ == '__main__':# 数据库连接配置 db_config = {"host": 'localhost',"user": 'root',"passwd": '123456',"db": 'account',"port": 3306,"charset": 'utf8mb4'}db = DbPool(db_config)dt_list = db.op_query("select * from user where userid > %s order by userid desc limit 1", (23))for nd in dt_list:print(nd)res = db.op_update("update user set register_date = %s where userid > %s and userid < %s", ("2024-04-19 16:42:50", 17702, 17705))print("res is ", res)

8、总结

在本文中详细介绍了 flask 框架搭建 web 项目的全部流程以及注意事项,相对而言flask比较简单容易上手,主要是前端的配置和数据库的配置以及增删改查等操作。本文中所涉及的代码已经上传至 github, 欢迎交流学习。项目地址 flask_web。

作者:豫州牧
链接:https://juejin.cn/post/7382525876032552998

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

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

相关文章

vscode用vue框架1写一个登陆页面

目录 一、创建登录页面 二、构建好登陆页面的路由 三、编写登录页代码 1.添加基础结构 2.给登录页添加背景 3.解决填充不满问题 4.我们把背景的红颜色替换成背景图&#xff1a; 5.在页面中央添加一个卡片来显示登录页面 6.设置中间卡片页面的左侧 7.设置右侧的样式及…

华芯微特SWM34-使用定时器捕获快速解码EV1527编码

在无线应用领域&#xff0c;很多433Mhz和315Mhz的遥控器&#xff0c;红外探测器&#xff0c;门磁报警器&#xff0c;无线门铃等都使用EV1527编码格式来发射数据。发射和接收均有对应的RF芯片完成&#xff0c;而且成本极低&#xff08;目前市场价3毛钱不到&#xff09;。接收芯片…

复分析——第7章——ζ 函数和素数定理(E.M. Stein R. Shakarchi)

第7章 ζ函数和素数定理 Bernhard Riemann, whose extraordinary intuitive powers we have already mentioned, has especially renovated our knowledge of the distribution of prime numbers, also one of the most mysterious questions in mathematics. He has tau…

《中国尘肺病农民工调查报告(2023)》

这份报告由中华社会救助基金会大爱清尘基金发布。 《中国尘肺病农民工调查报告(2023)》是一份深入探讨中国尘肺病农民工现状与挑战的研究报告。报告不仅详细记录了尘肺病患者的生存困境、经济与医疗状况,还对政策的实施效果进行了评估,并提出了针对性的建议。通过对不同地区、…

Vitis Accelerated Libraries 学习笔记--Vision 库介绍

目录 1. 简介 2. 分类介绍 2.1 图像容器 2.2 图像处理基础 2.3 图像滤波和平滑 2.4 图像变换和增强 2.5 图像分析和特征检测 2.6 数学和算术操作 2.7 图像校正和优化 2.8 颜色和阈值处理 2.9 高级图像处理 2.10 光流和运动估计 2.11 图像转换和映射 2.12 其他特殊…

Android Media Framework(八)OMXNodeInstance - Ⅰ

OpenMAX框架的学习有两大难点&#xff0c;一是组件的状态切换与buffer的流转过程&#xff0c;这部分内容我们已经在IL Spec中学习过了&#xff1b;二是OMX组件使用的buffer类型与buffer分配过程&#xff0c;这一节我们来重点剖析OMX组件使用的buffer类型。 1、引言 在实际应用…

业务架构交付物

背景 业务的核心元素、扩展元素以及它们的协同关系&#xff0c;业务架构和其他架构的关系等等已经有了不少认识&#xff0c;那么&#xff0c;通过对业务架构的还原和分析&#xff0c;到底能够得到什么业务架构的内容呢&#xff1f;它可以是一套流程框架体系&#xff0c;也可以…

探索约束LLM输出JSON的应用

0、 引言 JSON&#xff08;JavaScript Object Notation&#xff09;因其简洁、易读和易于解析的特性&#xff0c;已成为全球使用最广泛的数据交换格式之一。它能够满足各种数据交换需求&#xff0c;特别是在构建人工智能驱动的应用程序时&#xff0c;工程师们经常需要将大型语…

深度学习工具|LabelImg(标注工具)的安装与使用教程

1 简介 Label是一款免费的图像标注软件&#xff0c;可以以矩形框的形式对图像中的物体进行标记&#xff0c;常用于分类和目标检测。并可以将标记信息保存为PasclVOC&#xff08;xml&#xff09;、YOLO&#xff08;txt&#xff09;、CreateML&#xff08;json&#xff09;格式。…

Python中对含有转义字符的变量,如何处理

file_path C:\Users\EDY\PJ-IPAStudio\designer\project 这是一个路径的字符串&#xff0c;要访问这个路径下的文件&#xff0c;是会报错的 file_path rC:\Users\EDY\PJ-IPAStudio\designer\project 需要在前面添加 r 如果他是一个变量&#xff0c;如何对变量里的字符修改呢&…

0802功放2

功放要记一般的式子&#xff0c;而非最大的式子&#xff0c;因为总不能总开到最大音量上工作&#xff0c;而是在比较合适的音量上工作 运放的最大电压也是比电源低1~2V 饱和三极管的功率&#xff0c;电流越大&#xff0c;饱和压降越大&#xff1f;&#xff1f;&#xff1f;不…

STM32G474的浮点数四则运算速度实测

一、FPU的启用 FPU 即浮点运算单元&#xff08;Float Point Unit&#xff09;。浮点运算&#xff0c;对于定点 CPU&#xff08;没有 FPU 的 CPU&#xff09;来说必须要按照 IEEE-754 标准的算法来完成运算&#xff0c;是相当耗费时间的。而对于有 FPU 的 CPU来说&#xff0c;浮…

【Golang】Steam 创意工坊 Mod 文件夹批量重命名

本文将介绍一个使用Go语言编写的脚本&#xff0c;其主要功能是解析XML文件并基于解析结果重命名文件夹。这个脚本适用于需要对文件夹进行批量重命名&#xff0c;并且重命名规则依赖于XML文件内容的情况。 脚本功能概述 Steam创意工坊下载的Mod文件夹批量重命名为id名称 运行前…

Tomcat get请求传数组集合参数

前言 最近做项目&#xff0c;需要通过GET传参&#xff0c;来实现查询的能力&#xff0c;本来是RPC调用&#xff0c;直接参数序列化即可。但是服务最近修改为HTTP&#xff0c;本来Spring Cloud的feign也可以直接传参数&#xff0c;但是当使用Nginx访问时参数到底传啥呢&#xf…

iOS Swift5 视频播放

文章目录 1.截图2.代码3.导入本地文件 1.截图 2.代码 import UIKit import AVKit import AVFoundationclass ViewController: UIViewController {override func viewDidLoad() {super.viewDidLoad()view.backgroundColor .white// 创建按钮let button UIButton(type: .syste…

【学习】程序员资源网站

1 书栈网 简介&#xff1a;书栈网是程序员互联网IT开源编程书籍、资源免费阅读的网站&#xff0c;在书栈网你可以找到很多书籍、笔记资源。在这里&#xff0c;你可以根据热门收藏和阅读查看大家都在看什么&#xff0c;也可以根据技术栈分类找到对应模块的编程资源&#xff0c;…

通过InoDriverShop伺服调试软件连接汇川SV660F系列伺服的具体方法(以太网)

通过InoDriverShop伺服调试软件连接汇川SV660F系列伺服的具体方法(以太网) 具体连接伺服驱动器的步骤可参考以下内容: 启动InoDriverShop, 新建或打开工程 如下图所示,选择在线,选中SV660F图标,右侧通信类型选择“TCP—DCP”,点击下一步,同时要选择自己当前使用的网卡…

【扩散模型(一)】Stable Diffusion中的重建分支(reconstruction branch)和条件分支(condition branch)

Stable Diffusion 是一种基于扩散模型的生成模型&#xff0c;用于生成图像等数据。在解释 Stable Diffusion 的过程中&#xff0c;经常会提到两个主要的分支&#xff1a;重建分支&#xff08;reconstruction branch&#xff09;和条件分支&#xff08;condition branch&#xf…

C++多线程异步日志实现

使用C11标准&#xff0c;构建了一个方便使用的、轻量化的日志系统。封装线程安全的lockQueue&#xff0c;实现对每条日志添加信息、push到lockQueue中的LogTmp类&#xff0c;实现一个多线程异步的日志系统Logger。 lockqueue.h #pragma once #include <queue> #include…

Go微服务: redis分布式锁保证数据原子操作的一致性

概述 随着云计算和大数据技术的飞速发展&#xff0c;分布式系统已经成为现代IT架构的重要组成部分在分布式系统中&#xff0c;数据的一致性是一个至关重要的挑战&#xff0c;特别是在并发访问和修改共享资源的场景下分布式锁是一种跨进程、跨机器节点的互斥锁&#xff0c;用于…