flask要点与坑

news2024/11/15 4:47:29

简介

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

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

Flask 日志配置

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

# 日志模配置
# coding : utf-8

import os
import logging
from logging.handlers import RotatingFileHandler


def init_app(app):
    '''
    param app : FLask实列(启动时的app)
    '''
	basedir = os.path.abspath(os.path.dirname(__file__))
	# Formatter
	formatter = 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_path
	app.config['LOG_PATH_INFO'] = log_info
	app.config['LOG_FILE_MAX_BYTES'] = 100 * 1024 * 1024

	# 轮转数量是 10 个
	app.config['LOG_FILE_BACKUP_COUNT'] = 10
	# FileHandler Info
	file_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_app

app = 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_app

app = 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-8

from flask import Blueprint
from flask import render_template

home_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_template

login_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_blue

def 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_route

app = 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_app

app = 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 SQLAlchemy

Base = declarative_base()
metadata = Base.metadata

class 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 db

app = 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 timedelta

app = 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 session

def func():
    # ...
    session['user_id'] = user.ID
    session['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 re

def main():
	HOST = config.APP_HOST
	PORT = config.APP_PORT
	if 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_addr

	http_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_app

app = 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.coloradmin.cn/o/1014332.html

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

相关文章

浅谈拓展欧几里得算法

1、求特解 x 0 , y 0 x_0, y_0 x0​,y0​ 普通的欧几里得算法依据是辗转相除法&#xff0c;也就是&#xff0c;比如求 a &#xff0c; b a&#xff0c;b a&#xff0c;b 的最大公约数&#xff0c; a &#xff0c; b a&#xff0c;b a&#xff0c;b 进行辗转相除直到 a − b …

复盘:细数这些年写文字的成与败

引言 最近一直在思考和复盘&#xff0c;要说我这些年最后悔没坚持或者没做对的一件事就是没有好好写文字。时间过得很快&#xff0c;一晃笔者已经快毕业十年了&#xff0c;文章写得比较密集的时候还是大学时代和毕业头几年&#xff0c;后面输出就越来越少了&#xff0c;甚至一…

前端性能优化:提升网站速度与用户体验的终极指南

&#x1f482; 个人网站:【工具大全】【游戏大全】【神级源码资源网】&#x1f91f; 前端学习课程&#xff1a;&#x1f449;【28个案例趣学前端】【400个JS面试题】&#x1f485; 寻找学习交流、摸鱼划水的小伙伴&#xff0c;请点击【摸鱼学习交流群】 在今天的数字时代&#…

【C++ 学习 ㉑】- 详解 map 和 set(上)

目录 一、C STL 关联式容器 二、pair 类模板 三、set 3.1 - set 的基本介绍 3.2 - set 的成员函数 3.1.1 - 构造函数 3.1.2 - 迭代器 3.1.3 - 修改操作 3.1.4 - 其他操作 四、map 4.1 - map 的基本介绍 4.2 - map 的成员函数 4.2.1 - 迭代器 4.2.2 - operator[] …

避免使用违规词,企业新媒体营销应注重品牌形象维护

随着越来越多的主体入局新媒体平台&#xff0c;为了维护平台健康的内容生态和创造良好的社区氛围&#xff0c;社交平台在内容上的监管越发严格。 不可避免的&#xff0c;很多做新媒体营销的企业开始陷入与平台审核的“拉扯”之中。 为了让品牌账号在各平台上顺利运营&#xff0…

二十一、MySQL(多表)内连接、外连接、自连接实现

1、多表查询 &#xff08;1&#xff09;基础概念&#xff1a; &#xff08;2&#xff09;多表查询的分类&#xff1a; 2、内连接 &#xff08;1&#xff09;基础概念&#xff1a; &#xff08;2&#xff09;隐式内连接&#xff1a; 基础语法&#xff1a; select 表1.name,…

使用Oracle自带SqlPlus导入导出数据库脚本

sqlplus sys/passwordorcl as sysdba ----cmd 进入Oracle sqlplus 1、导入例子&#xff1a; imp username/username127.0.0.1:1521/orcl fileD:\datasource\username0919.dmp fully imp 用户名/密码127.0.0.1:1521/orcl fileD:\datasource\备份名字.dmp fully 2、导出例子&a…

Redis实战:在CentOS 7上安装部署与应用探索

PS&#xff1a;文章最后有“开心一刻”&#xff0c;记得看哦&#xff0c;给生活增加点儿趣味。 一、Redis初识 Redis&#xff0c;全称Remote Dictionary Server&#xff0c;是一个开源的键值对存储数据库。它支持多种数据类型&#xff0c;如字符串、列表、集合、有序集合、哈希…

SpringBoot-接口幂等性

幂等 幂等操作的特点是其任意多次执行所产生的影响均与一次执行的影响相同。 幂等函数或幂等方法是指可以使用相同参数重复执行&#xff0c;并能获得相同结果的函数。这些函数不会影响系统状态&#xff0c;也不用担心重复执行会对系统造成改变。 尤其是支付、订单等与金钱挂…

进程创建fork函数

#include <sys/types.h> #include <unistd.h> pid_t fork(void); 函数的作用&#xff1a;用于创建子进程。 返回值&#xff1a; fork()的返回值会返回两次。一次是在父进程&#xff0c;一次是在子进程。 父进程中&#xff1a;返回创建的子进程的ID&#xff0c;返回…

ITIL 4指导、计划和改进—沟通和组织变革管理

第6章 沟通和组织变革管理 提供IT支持的产品和服务不仅是一种操纵技术的练习&#xff0c;而且是人类的努力。服务提供的各个方面都表现得更好&#xff0c;具有良好的沟通和对人为因素的关注。问题通常可以追溯到不正确、不匹配或时间错误的信息。人们需要帮助以适应变化中的组…

卖出看跌期权策略(Short Put)

卖出看跌期权策略&#xff08;Short Put&#xff09; 看跌期权的买家有权利按照期权的行权价卖出标的资产&#xff0c;看跌期权的卖家有义务按照期权的行权价买入标的资产。通过承担按照特定价格买入标的资产的义务&#xff0c;看跌期权的卖家可以收到期权的权利金&#xff0c…

深入解析 qsort 函数(下),用冒泡排序模拟实现 qsort 函数

前言&#xff1a;对于库函数有适当了解的朋友们&#xff0c;对于 qsort 函数想必是有认知的&#xff0c;因为他可以对任意数据类型进行排序的功能属实是有点厉害的&#xff0c;本次分享&#xff0c;笔者就给大家带来 qsort 函数的全面的解读 本次知识的分享笔者分为上下俩卷文章…

LeetCode:两数之和

题目描述&#xff1a; 这是一道用暴力解法&#xff0c;逻辑十分简单、清晰的一道题&#xff0c;直接遍历数target-num[i]就行 而官方给了第二种巧妙的解法&#xff1a;运用哈希表。此法可将时间复杂度从O&#xff08;N^2&#xff09;降到O&#xff08;1&#xff09; 其思路是…

rhel8防火墙firewalld操作

1.查看默认区域 [rootlocalhost r]# firewall-cmd --get-default-zone public2.查看网卡关联的区域 [rootlocalhost r]# firewall-cmd --get-zone-of-interfaceifcfg-ens160 external 3.设置网卡的默认区域修改为work [rootlocalhost r]# firewall-cmd --zonework --change…

综合管廊安全监测,助力市政管廊智能化管理

综合管廊是一种集管线维护、建设、管理于一体的地下综合通道&#xff0c;可以将电力、通讯、燃气、供热、供水等工程管线集于一体&#xff0c;综合管廊对于城市建设具有重要意义&#xff0c;可以防止管线破裂&#xff0c;杜绝反复开挖路面&#xff0c;有效缓解交通拥堵&#xf…

ISAC通信感知一体化学习记录

文章目录 写在前面Fundamental Limits for ISAC: Information and Communication Theoretic PerspectiveIntroductionperformance metricsCommunication and Estimation Rates PHY Tradeoff and Resource Allocation for ISACbackgroundThe Related Works Preliminaries of the…

JDK9特性——概述

文章目录 引言JDK9特性概述JDK9的改变JDK和JRE目录变化总结 引言 JAVA8 及之前&#xff0c;版本都是特性驱动的版本更新&#xff0c;有重大的特性产生&#xff0c;然后进行更新。 JAVA9开始&#xff0c;JDK开始以时间为驱动进行更新&#xff0c;以半年为周期&#xff0c;到时…

淘宝问大家怎么投诉不良评价?

大花客服外包 商家朋友们都知道&#xff0c;正向的“问大家”可以很大程度提高转化率&#xff0c;负面的会对转化率有很不好的影响。那当遇到“问大家”中存在不良内容时&#xff0c;该如何投诉呢&#xff1f; 一、手机淘宝APP举报问大家不良内容 【问大家的提问】举报受理范围…

Makefile基础

迷途小书童 读完需要 4分钟 速读仅需 2 分钟 1 引言 下面这个 C 语言的代码非常简单 #include <stdio.h>int main() {printf("Hello World!.\n");return 0; } 在 Linux 下面&#xff0c;我们使用下面的命令编译就可以 gcc hello.c -o hello 但是随着项目的变大…