flask要点与坑

简介

Flask是一个用Python编写的Web应用程序框架,该框架简单易用、模块化、灵活性高。

该笔记主要记录Flask的关键要点和容易踩坑的地方

Flask 日志配置

Flask 中的自带logger模块(也是python自带的模块),通过简单配置可以实现将日志记录到日志文件中(记录关键日志有助于以后分析问题);更详细的logging配置可以自行去百度。

# 日志模配置
# coding : utf-8import os
import logging
from logging.handlers import RotatingFileHandlerdef init_app(app):'''param app : FLask实列(启动时的app)'''basedir = os.path.abspath(os.path.dirname(__file__))# Formatterformatter = logging.Formatter('%(asctime)s %(levelname)s %(lineno)s %(message)s')# 日志配置log_path = LOG_PATH = os.path.join(basedir, 'logs')log_info = os.path.join(log_path, 'flask.log')if not os.path.exists(log_path):os.mkdir(log_path)app.config['LOG_PATH'] = log_pathapp.config['LOG_PATH_INFO'] = log_infoapp.config['LOG_FILE_MAX_BYTES'] = 100 * 1024 * 1024# 轮转数量是 10 个app.config['LOG_FILE_BACKUP_COUNT'] = 10# FileHandler Infofile_handler_info = RotatingFileHandler(filename=log_info)file_handler_info.setFormatter(formatter)file_handler_info.setLevel(logging.INFO)app.logger.addHandler(file_handler_info)
from flask import Flask
from log_hander import init_appapp = Flask(__name__)init_app(app)@app.route('/')
def test():app.logger.info('hello world')return "hello world"

正常情况下,日志(flask.log)中会输出 ”hello world“信息,但实际情况却没有

这里有个坑,就是在init_app 函数最后需要再加上一段代码:

 app.logger.setLevel(logging.INFO) 

这个问题困扰我很长时间

Flask Blueprint

Flask的简单之处就是一个py文件就可以创建一个http服务

from flask import Flask
from log_hander import init_appapp = Flask(__name__)@app.route('/',methods=["GET"])
def test():app.logger.info('hello world')return "hello world"
# 添加任意数量的 处理函数
app.run()

实际项目中不能把所有的业务处理都放到一个py文件中,那么就需要划分模块了。

蓝图(Blueprint)可以帮助我们划分模块(有点类似asp.net mvc、java springboot中的控制器)

一般的做法:建立一个python包,在里面添加我们的模块文件(根据业务划分),每个模块中定义一个蓝图(Blueprint),最后在app中注册蓝图(Blueprint)。

home.py 模块

# coding : utf-8from flask import Blueprint
from flask import render_templatehome_blue=Blueprint('home',__name__)# 访问路径
# http://ip:port/home
# http://ip:port/home/index
@home_blue.route('/',methods=['GET'])
@home_blue.route('/index',methods=['GET'])
def index():'''首页@return render_template'''return render_template('index.html',title='Home Page')@home_blue.route('/welcom',methods=['GET'])
def welcomPage():return render_template('welcome_iframe.html',title='Welcom Page')pass

login.py 模块

# coding : utf-8
from flask import Blueprint
from flask import render_templatelogin_blue = Blueprint('login', __name__)# 访问路径
# http://ip:port/
# http://ip:port/index@login_blue.route('/', methods=['GET'])
@login_blue.route('/index', methods=['GET'])
def index():'''登陆首页@return render_template'''if user_id == None:return render_template('login.html',title='登录页')@login_blue.route('/login_user', methods=['POST'])
def user_login():'''登录:return:'''try:# 登录逻辑return jsonify(common_tools.get_res_model(None, '验证通过', True))except:return jsonify(common_tools.get_res_model(None, '验证未通过', False))

_init_.py

# coding : utf-8
from flaskAdmin.views.home import home_blue
from flaskAdmin.views.login import login_bluedef init_route(app):app.register_blueprint(login_blue,url_prefix='/')app.register_blueprint(home_blue,url_prefix='/home')

app.py中设置

from flask import Flask
from my_moudle import init_routeapp = Flask(__name__)
init_route(app)app.run()

templates 过滤器

在Flask中,过滤器(filters)是一种用于处理输入并生成输出的函数,用于在模板渲染过程中转换数据。Flask内置了多种过滤器,同时支持自定义过滤器。这里主要是说过自定义过滤器

app中定义过滤器

使用@app.template_filter(“filter name”) 添加

from flask import Flask
from log_hander import init_appapp = Flask(__name__)@app.template_filter("format_float") 
def formater_float(val:float):'''定义一个格式化浮点数据的过滤器'''return "{:.2f}".format(val)app.run()

使用过滤器

<div>{{my_value|format_float}}
</div>

Blueprint中定义

使用@blue.app_template_filter(“filter name”)添加

@blue.app_template_filter("format_float")
def formater_float(val:float):'''定义一个格式化浮点数据的过滤器'''return "{:.2f}".format(val)

注意:Blueprint中定义的过滤器是全局的,所有模板都可以使用

ORM

sqlalchemy 框架是我的首选。

安装:pip install Flask-SQLAlchemy

model定义

# coding: utf-8
from sqlalchemy import Column, DateTime, String, Text
from sqlalchemy.dialects.mysql import INTEGER
from sqlalchemy.ext.declarative import declarative_base
from flask_sqlalchemy import SQLAlchemyBase = declarative_base()
metadata = Base.metadataclass User(Base):__tablename__ = 'user'# 指定ID对应的数据字段(model定义字段与数据字段不一致时)ID = Column("uuid",String(64, 'utf8_bin'), primary_key=True) UserCode = Column(INTEGER(11), nullable=False)UserRealName = Column(String(64, 'utf8_bin'), nullable=False)DelFlag = Column(String(2, 'utf8_bin'), nullable=False)PassWord = Column(String(128, 'utf8_bin'), nullable=False)Remark = Column(Text(collation='utf8_bin'))CreateDate = Column(DateTime, nullable=False, comment='创建日期')LastLoginTime = Column(DateTime, comment='最后一次登录日期')ValidityOfTime = Column(DateTime, comment='账户有效期')UserRole = Column(String(64, 'utf8_bin'), nullable=True)# ...
db = SQLAlchemy()

app.py 中配置

from flask import Flask
from db_model import dbapp = Flask(__name__)# 关键步骤
# SQLALCHEMY_DATABASE_URI  数据库连接字符串
app.config["SQLALCHEMY_DATABASE_URI"] = 'mysql+pymysql://usermame:password@host:port/dbname?charset=utf8'
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = True # 跟踪对象修改,有点类似EF中的状态跟踪
app.config["SQLALCHEMY_ECHO"] = False # 是否打印SQL日志
db.init(app)app.run()

Session

web离不开session。可以使用Flask-Session模块,也可以自定义实现(原理并不复杂,这里不罗嗦了)

安装:pip install Flask-Session

app.py 中配置

from flask import Flask
from datetime import timedeltaapp = Flask(__name__)app.config["SESSION_TYPE"]='redis' # 需要额外安装redis模块
app.config["SESSION_REDIS"]=Redis(host="127.0.0.1",port=6379)
app.config["SESSION_USE_SIGNER"]=True # 使用字符存储
app.config["SECRET_KEY"]='FLASK_SYSADMIN' # session 加密key
app.config["SESSION_PERMANENT"]=False
app.config["PERMANENT_SESSION_LIFETIME"]=timedelta(seconds=60*20) # session超时时间app.run()

使用方式

# 导入session模块
from flask import sessiondef func():# ...session['user_id'] = user.IDsession['user_code'] = user.UserCode# ...

建议将session信息存储的redis中,方便后期分布式部署或作集群时共享登录信息

部署

Flask自带一个服务器,但是也明确指出自带的服务器只能用于开发环境,不能用于生产环境。

linux

Linux环境可以使用uwsgi部署,但是uwsgi需要自己编译。有兴趣的化可以百度查一下,这里不推荐。

windows

windows环境下可以部署到IIS中(IIS最低版本7.0,至少时winserver 2008以后的版本),IIS中部署python web的机会不多,但网上确实有部署教程,有兴趣的可以自行搜索。

uvicorn 、tornado承载

uvicorn 、tornado也是python的一种web框架,是一种异步框架,与Flask结合可以降低部署难度,还可以享受Flask开发带来的便利。

这里演示一下tornado的承载方式:

将Flask主项目放到一个pathon包中,经app的声明迁移到_init_.py 中

在这里插入图片描述

runserver.py

# coding: utf-8
from tornado.wsgi import  WSGIContainer
from tornado.httpserver import HTTPServer
from tornado.ioloop import IOLoop
from flaskAdmin import app,config
import sys
import redef main():HOST = config.APP_HOSTPORT = config.APP_PORTif len(sys.argv) == 3:_ip_check=r"^(\d{1,3}\.){3}\d{1,3}$"ip_addr = sys.argv[1]ip_port = sys.argv[2]if re.match(_ip_check,ip_addr) !=None and re.match(r'^[1-9]\d{1,5}$',ip_port)!=None:PORT=int(ip_port)HOST=ip_addrhttp_server=HTTPServer(WSGIContainer(app))http_server.listen(PORT,HOST)IOLoop.instance().start()if __name__ == '__main__':main()

使用uvicorn 、tornado承载需要注意一点:如果你的服务需要处理高并发的场景,一定要在服务的前面加一个代理来限制最高并发数量,否则你的服务可能会出现崩溃的情况;这是uvicorn 、tornado一个大坑,两个库都没有做最大并发限制,如果并发超过服务器主机的最大限制,操作系统会报一个 select描述符错,而这两个库并不处理这个异常(针对这个问题stackoverflow论坛上有很多人吐槽)。

https

生成密钥(windows环境下需要自行安装openssl):

# 生成私钥,按照提示填写内容
openssl genrsa -des3 -out server.key 1024# 生成csr文件 ,按照提示填写内容
openssl req -new -key server.key -out server.csr# Remove Passphrase from key
cp server.key server.key.org 
openssl rsa -in server.key.org -out server.key# 生成crt文件,有效期1年(365天)
openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt

Flask app中配置的方式

from flask import Flask
from log_hander import init_appapp = Flask(__name__)if __name__ == "__main__":app.run(host='127.0.0.1',port=10262,ssl_context = ("SLL_CRT_PATH","SSL_KEY_PATH")) # 设置ssl 密钥路径

tornado承载中配置

如果使用tornado承载部署,可以在tornado.httpserver.HTTPServer中设置密钥

http_server=HTTPServer(WSGIContainer(app),ssl_options={"certfile":"SLL_CRT_PATH","keyfile":"SSL_KEY_PATH"})

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

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

相关文章

SpringMVC之JSON数据返回与异常处理机制

目录 一.SpringMVC的JSON数据返回 1.导入Maven依赖 2.配置spring-mvc.xml 3.ResponseBody注解的使用 3.1案例演示 1.List集合转JSON 2.Map集合转JSON 3.返回指定格式String 4. ResponseBody用法 5.Jackson 5.1介绍 5.2常用注解 二.异常处理机制 1.为什么要全局异常处…

Jenkins :添加node权限获取凭据、执行命令

拥有Jenkins agent权限的账号可以对node节点进行操作&#xff0c;通过添加不同的node可以让流水线项目在不同的节点上运行&#xff0c;安装Jenkins的主机默认作为master节点。 1.Jenkins 添加node获取明文凭据 通过添加node节点&#xff0c;本地监听ssh认证&#xff0c;选则凭…

详解TCP/IP协议第三篇:通信数据在OSI通信模型的上下传输

文章目录 一&#xff1a;OSI通信模型间数据传输展示 二&#xff1a;应用层到会话层解析 1&#xff1a;应用层 2&#xff1a;表现层 3&#xff1a;会话层 三&#xff1a;传输层到物理层解析 1&#xff1a;传输层 2&#xff1a;网络层 3&#xff1a;数据链路层、与物理层…

考研算法47天:01背包

问题描述 算法详细步骤 代码随想录 (programmercarl.com) ac代码 #include <iostream> using namespace std; int bag[1001]; int bagMax[1001]; int bagvalue[1001]; int main(){int n,v;cin>>n>>v;for(int i0;i<n;i){cin>>bag[i]>>bagva…

【C++杂货铺】继承由浅入深详细总结

文章目录 一、继承的概念及定义1.1 继承的概念1.2 继承定义1.2.1 定义格式1.2.2 继承方式和访问限定符1.2.3 继承基类成员访问方式的变化 二、基类和派生类对象赋值转换三、继承中的作用域四、派生类中的默认成员函数4.1 默认构造函数4.2 拷贝构造函数4.3 赋值运算符重载函数4.…

【C++】动态规划题目总结(随做随更)

文章目录 一. 斐波那契数列模型1. 第 N 个泰波那契数2. 三步问题3. 使用最小花费爬楼梯解法一&#xff1a;从左往右填表解法二&#xff1a;从右往左填表 一. 斐波那契数列模型 解题步骤&#xff1a; 确定状态表示&#xff08;最重要&#xff09;&#xff1a;明确dp表里的值所…

PYTHON-模拟练习题目集合

&#x1f308;write in front&#x1f308; &#x1f9f8;大家好&#xff0c;我是Aileen&#x1f9f8;.希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流. &#x1f194;本文由Aileen_0v0&#x1f9f8; 原创 CSDN首发&#x1f412; 如…

Python的get请求报错Error: Unexpected status code 400

一句话导读&#xff1a; 最近在做研发效能提升的事情&#xff0c;其中有一块就是要对项目管理相关数据做统计&#xff0c;我们使用的是ones做的项目管理&#xff0c;ones本身带的那些报表满足不了我们的需求&#xff0c;就想着看这些数据是不是能自己拿出来做统计&#xff0c;有…

浅谈C++|多态篇

1.多态的基本概念 多态是C面向对象三大特性之一多态分为两类 1. 静态多态:函数重载和运算符重载属于静态多态&#xff0c;复用函数名 2.动态多态:派生类和虚函数实现运行时多态 静态多态和动态多态区别: 静态多态的函数地址早绑定–编译阶段确定函数地址 动态多态的函数地址晚绑…

Linux学习之平均负载的概念和查看方法

先理解一下平均负载的含义&#xff1a; 平均负载是指单位时间内&#xff0c;系统处于可运行状态和不可中断状态的进程数&#xff0c;也可以看成平均活跃进程数。 可运行状态的进程&#xff1a; 正在使用CPU或者正在等待CPU处理的进程&#xff0c;ps 命令看到的&#xff0c;处于…

黑马JVM总结(十)

&#xff08;1&#xff09;直接内存_基本使用 下面我们看一下使用了ByteBuffer直接内存&#xff0c;大文件的读写效率是非常的高 Java本身并不具备磁盘读写的能力&#xff0c;它需要调用操作系统的函数&#xff0c;需要从java的方法内部调用本地方法操作系统的方法&#xff0c…

bboss 流批一体化框架 与 数据采集 ETL

数据采集 ETL 与 流批一体化框架 特性&#xff1a; 高效、稳定、快速、安全 bboss 是一个基于开源协议 Apache License 发布的开源项目&#xff0c;主要由以下三部分构成&#xff1a; Elasticsearch Highlevel Java Restclient &#xff0c; 一个高性能高兼容性的Elasticsea…

【C刷题】day2

一、选择题 1、以下程序段的输出结果是&#xff08; &#xff09; #include<stdio.h> int main() { char s[] "\\123456\123456\t"; printf("%d\n", strlen(s)); return 0; } A: 12 B: 13 C: 16 D: 以上都不对【答案】&#xff1a; A 【解析】…

Python Opencv实践 - 视频文件写入(格式和分辨率修改)

参考资料&#xff1a; python opencv写视频——cv2.VideoWriter()_cv2.cv.videowriter(_翟羽嚄的博客-CSDN博客 import cv2 as cv import numpy as np#1. 打开原始视频 video_in cv.VideoCapture("../SampleVideos/Unity2D.mp4") video_width int(video_in.get(c…

带你了解前后端分离的秘密-Vue【vue入门】

&#x1f3c5;我是默&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; &#x1f31f;在这里&#xff0c;我要推荐给大家我的专栏《Vue》。&#x1f3af;&#x1f3af; &#x1f680;无论你是编程小白&#xff0c;还是有一定基础的程序员&#xff0c;这个专栏…

无涯教程-JavaScript - ATAN2函数

描述 The ATAN2 function returns the arctangent, or inverse tangent, of the specified x- and ycoordinates, in radians, between -π/2 and π/2. 语法 ATAN2 (x_num, y_num)争论 Argument描述Required/OptionalX_numThe x-coordinate of the point.RequiredY_numThe…

用c++实现五子棋小游戏

五子棋是一款经典小游戏&#xff0c;今天我们就用c实现简单的五子棋小游戏 目录 用到的算法&#xff1a; 思路分析 定义变量 开始写代码 完整代码 结果图&#xff1a; 用到的算法&#xff1a; 合法移动的判断&#xff1a;isValidMove 函数通过检查指定位置是否在棋盘范…

游戏视频录制软件对比,哪款最适合你的需求?

随着电子竞技和游戏直播行业的迅速崛起&#xff0c;越来越多的玩家渴望记录并分享自己在游戏中的精彩瞬间。游戏视频录制软件正是满足这一需求的关键工具。本文将针对三款优秀的游戏视频录制软件进行对比分析&#xff0c;以便为读者提供选购建议。 游戏视频录制软件1&#xff1…

十天学完基础数据结构-第一天(绪论)

1. 数据结构的研究内容 数据结构的研究主要包括以下核心内容和目标&#xff1a; 存储和组织数据&#xff1a;数据结构研究如何高效地存储和组织数据&#xff0c;以便于访问和操作。这包括了在内存或磁盘上的数据存储方式&#xff0c;如何将数据元素组织成有序或无序的集合&…

移动端H5封装一个 ScrollList 横向滚动列表组件,实现向左滑动

效果&#xff1a; 1.封装组件&#xff1a; <template><div class"scroll-list"><divclass"scroll-list-content":style"{ background, color, fontSize: size }"ref"scrollListContent"><div class"scroll…