分享web开发知识

注册/登录|最近发布|今日推荐

主页 IT知识网页技术软件开发前端开发代码编程运营维护技术分享教程案例
当前位置:首页 > IT知识

web框架之Flask

发布时间:2023-09-06 01:21责任编辑:林大明关键词:暂无标签

Flask是一个基于Python开发并且依赖jinja2模板和Werkzeug WSGI服务的一个微型框架,对于Werkzeug本质是Socket服务端,其用于接收http请求并对请求进行预处理,然后触发Flask框架,开发人员基于Flask框架提供的功能对请求进行相应的处理,并返回给用户,如果要返回给用户复杂的内容时,需要借助jinja2模板来实现对模板的处理,即:将模板和数据进行渲染,将渲染后的字符串返回给用户浏览器。

“微”(micro) 并不表示你需要把整个 Web 应用塞进单个 Python 文件(虽然确实可以 ),也不意味着 Flask 在功能上有所欠缺。微框架中的“微”意味着 Flask 旨在保持核心简单而易于扩展。Flask 不会替你做出太多决策——比如使用何种数据库。而那些 Flask 所选择的——比如使用何种模板引擎——则很容易替换。除此之外的一切都由可由你掌握。如此,Flask 可以与您珠联璧合。

默认情况下,Flask 不包含数据库抽象层、表单验证,或是其它任何已有多种库可以胜任的功能。然而,Flask 支持用扩展来给应用添加这些功能,如同是 Flask 本身实现的一样。众多的扩展提供了数据库集成、表单验证、上传处理、各种各样的开放认证技术等功能。Flask 也许是“微小”的,但它已准备好在需求繁杂的生产环境中投入使用。

安装Flask

pip3 install flask

Werkzeug :

from werkzeug.wrappers import Request, Response@Request.applicationdef hello(request): ???return Response(‘Hello World!‘)if __name__ == ‘__main__‘: ???from werkzeug.serving import run_simple ???run_simple(‘localhost‘, 4000, hello)

基本使用

from flask import Flaskapp = Flask(__name__) @app.route(‘/‘)def hello_world(): ???return ‘Hello World!‘ if __name__ == ‘__main__‘: ???app.run()

配置文件

flask中的配置文件是一个flask.config.Config对象(继承字典),默认配置为: ???{ ???????‘DEBUG‘: ???????????????????????????????get_debug_flag(default=False), ?是否开启Debug模式 ???????‘TESTING‘: ?????????????????????????????False, ?????????????????????????是否开启测试模式 ???????‘PROPAGATE_EXCEPTIONS‘: ????????????????None, ?????????????????????????????????‘PRESERVE_CONTEXT_ON_EXCEPTION‘: ???????None, ???????‘SECRET_KEY‘: ??????????????????????????None, ???????‘PERMANENT_SESSION_LIFETIME‘: ??????????timedelta(days=31), ???????‘USE_X_SENDFILE‘: ??????????????????????False, ???????‘LOGGER_NAME‘: ?????????????????????????None, ???????‘LOGGER_HANDLER_POLICY‘: ??????????????‘always‘, ???????‘SERVER_NAME‘: ?????????????????????????None, ???????‘APPLICATION_ROOT‘: ????????????????????None, ???????‘SESSION_COOKIE_NAME‘: ?????????????????‘session‘, ???????‘SESSION_COOKIE_DOMAIN‘: ???????????????None, ???????‘SESSION_COOKIE_PATH‘: ?????????????????None, ???????‘SESSION_COOKIE_HTTPONLY‘: ?????????????True, ???????‘SESSION_COOKIE_SECURE‘: ???????????????False, ???????‘SESSION_REFRESH_EACH_REQUEST‘: ????????True, ???????‘MAX_CONTENT_LENGTH‘: ??????????????????None, ???????‘SEND_FILE_MAX_AGE_DEFAULT‘: ???????????timedelta(hours=12), ???????‘TRAP_BAD_REQUEST_ERRORS‘: ?????????????False, ???????‘TRAP_HTTP_EXCEPTIONS‘: ????????????????False, ???????‘EXPLAIN_TEMPLATE_LOADING‘: ????????????False, ???????‘PREFERRED_URL_SCHEME‘: ????????????????‘http‘, ???????‘JSON_AS_ASCII‘: ???????????????????????True, ???????‘JSON_SORT_KEYS‘: ??????????????????????True, ???????‘JSONIFY_PRETTYPRINT_REGULAR‘: ?????????True, ???????‘JSONIFY_MIMETYPE‘: ????????????????????‘application/json‘, ???????‘TEMPLATES_AUTO_RELOAD‘: ???????????????None, ???} 方式一: ???app.config[‘DEBUG‘] = True ????PS: 由于Config对象本质上是字典,所以还可以使用app.config.update(...) 方式二: ???app.config.from_pyfile("python文件名称") ???????如: ???????????settings.py ???????????????DEBUG = True ????????????app.config.from_pyfile("settings.py") ????app.config.from_envvar("环境变量名称") ???????环境变量的值为python文件名称名称,内部调用from_pyfile方法 ?????app.config.from_json("json文件名称") ???????JSON文件名称,必须是json格式,因为内部会执行json.loads ????app.config.from_mapping({‘DEBUG‘:True}) ???????字典格式 ????app.config.from_object("python类或类的路径") ????????app.config.from_object(‘pro_flask.settings.TestingConfig‘) ????????settings.py ????????????class Config(object): ???????????????DEBUG = False ???????????????TESTING = False ???????????????DATABASE_URI = ‘sqlite://:memory:‘ ????????????class ProductionConfig(Config): ???????????????DATABASE_URI = ‘mysql://user@localhost/foo‘ ????????????class DevelopmentConfig(Config): ???????????????DEBUG = True ????????????class TestingConfig(Config): ???????????????TESTING = True ????????PS: 从sys.path中已经存在路径开始写 ?????????PS: settings.py文件默认路径要放在程序root_path目录,如果instance_relative_config为True,则就是instance_path目录

路由系统

  • @app.route(‘/user/<username>‘)
  • @app.route(‘/post/<int:post_id>‘)
  • @app.route(‘/post/<float:post_id>‘)
  • @app.route(‘/post/<path:path>‘)
  • @app.route(‘/login‘, methods=[‘GET‘, ‘POST‘])

常用路由系统有以上五种,所有的路由系统都是基于一下对应关系来处理:

DEFAULT_CONVERTERS = { ???‘default‘: ?????????UnicodeConverter, ???‘string‘: ??????????UnicodeConverter, ???‘any‘: ?????????????AnyConverter, ???‘path‘: ????????????PathConverter, ???‘int‘: ?????????????IntegerConverter, ???‘float‘: ???????????FloatConverter, ???‘uuid‘: ????????????UUIDConverter,}

a.注册路由

def auth(func): ???????????def inner(*args, **kwargs): ???????????????print(‘before‘) ???????????????result = func(*args, **kwargs) ???????????????print(‘after‘) ???????????????return result ???????return inner ???????@app.route(‘/index.html‘,methods=[‘GET‘,‘POST‘],endpoint=‘index‘) ???????@auth ???????def index(): ???????????return ‘Index‘ ???????或 ???????????????def index(): ???????????return "Index" ???????self.add_url_rule(rule=‘/index.html‘, endpoint="index", view_func=index, methods=["GET","POST"]) ???????or ???????app.add_url_rule(rule=‘/index.html‘, endpoint="index", view_func=index, methods=["GET","POST"]) ???????app.view_functions[‘index‘] = index ???????或 ???????def auth(func): ???????????def inner(*args, **kwargs): ???????????????print(‘before‘) ???????????????result = func(*args, **kwargs) ???????????????print(‘after‘) ???????????????return result ???????return inner ???????class IndexView(views.View): ???????????methods = [‘GET‘] ???????????decorators = [auth, ] ???????????def dispatch_request(self): ???????????????print(‘Index‘) ???????????????return ‘Index!‘ ???????app.add_url_rule(‘/index‘, view_func=IndexView.as_view(name=‘index‘)) ?# name=endpoint ???????或 ???????class IndexView(views.MethodView): ???????????methods = [‘GET‘] ???????????decorators = [auth, ] ???????????def get(self): ???????????????return ‘Index.GET‘ ???????????def post(self): ???????????????return ‘Index.POST‘ ???????app.add_url_rule(‘/index‘, view_func=IndexView.as_view(name=‘index‘)) ?# name=endpoint ???????@app.route和app.add_url_rule参数: ???????????rule, ??????????????????????URL规则 ???????????view_func, ?????????????????视图函数名称 ???????????defaults=None, ?????????????默认值,当URL中无参数,函数需要参数时,使用defaults={‘k‘:‘v‘}为函数提供参数 ???????????endpoint=None, ?????????????名称,用于反向生成URL,即: url_for(‘名称‘) ???????????methods=None, ??????????????允许的请求方式,如:["GET","POST"] ???????????????????????strict_slashes=None, ???????对URL最后的 / 符号是否严格要求, ???????????????????????????????????????如: ???????????????????????????????????????????@app.route(‘/index‘,strict_slashes=False), ???????????????????????????????????????????????访问 http://www.xx.com/index/ 或 http://www.xx.com/index均可 ???????????????????????????????????????????@app.route(‘/index‘,strict_slashes=True) ???????????????????????????????????????????????仅访问 http://www.xx.com/index ????????????redirect_to=None, ??????????重定向到指定地址 ???????????????????????????????????????如: ???????????????????????????????????????????@app.route(‘/index/<int:nid>‘, redirect_to=‘/home/<nid>‘) ???????????????????????????????????????????或 ???????????????????????????????????????????def func(adapter, nid): ???????????????????????????????????????????????return "/home/888" ???????????????????????????????????????????@app.route(‘/index/<int:nid>‘, redirect_to=func) ???????????subdomain=None, ????????????子域名访问 ???????????????????????????????????????????????from flask import Flask, views, url_for ???????????????????????????????????????????????app = Flask(import_name=__name__) ???????????????????????????????????????????????app.config[‘SERVER_NAME‘] = ‘wupeiqi.com:5000‘ ???????????????????????????????????????????????@app.route("/", subdomain="admin") ???????????????????????????????????????????????def static_index(): ???????????????????????????????????????????????????"""Flask supports static subdomains ???????????????????????????????????????????????????This is available at static.your-domain.tld""" ???????????????????????????????????????????????????return "static.your-domain.tld" ???????????????????????????????????????????????@app.route("/dynamic", subdomain="<username>") ???????????????????????????????????????????????def username_index(username): ???????????????????????????????????????????????????"""Dynamic subdomains are also supported ???????????????????????????????????????????????????Try going to user1.your-domain.tld/dynamic""" ???????????????????????????????????????????????????return username + ".your-domain.tld" ???????????????????????????????????????????????if __name__ == ‘__main__‘: ???????????????????????????????????????????????????app.run() ???????a.注册路由原理
View Code

b.自定义正则路由匹配

from flask import Flask, views, url_for ???????????from werkzeug.routing import BaseConverter ???????????app = Flask(import_name=__name__) ???????????class RegexConverter(BaseConverter): ???????????????""" ???????????????自定义URL匹配正则表达式 ???????????????""" ???????????????def __init__(self, map, regex): ???????????????????super(RegexConverter, self).__init__(map) ???????????????????self.regex = regex ???????????????def to_python(self, value): ???????????????????""" ???????????????????路由匹配时,匹配成功后传递给视图函数中参数的值 ???????????????????:param value: ????????????????????:return: ????????????????????""" ???????????????????return int(value) ???????????????def to_url(self, value): ???????????????????""" ???????????????????使用url_for反向生成URL时,传递的参数经过该方法处理,返回的值用于生成URL中的参数 ???????????????????:param value: ????????????????????:return: ????????????????????""" ???????????????????val = super(RegexConverter, self).to_url(value) ???????????????????return val ???????????# 添加到flask中 ???????????app.url_map.converters[‘regex‘] = RegexConverter ???????????@app.route(‘/index/<regex("\d+"):nid>‘) ???????????def index(nid): ???????????????print(url_for(‘index‘, nid=‘888‘)) ???????????????return ‘Index‘ ???????????if __name__ == ‘__main__‘: ???????????????app.run()b. 自定制正则路由匹配
View Code

模板

1、模板的使用

Flask使用的是Jinja2模板,所以其语法和Django无差别

2、自定义模板方法

Flask中自定义模板方法的方式和Bottle相似,创建一个函数并通过参数的形式传入render_template,如:

html

<!DOCTYPE html><html><head lang="en"> ???<meta charset="UTF-8"> ???<title></title></head><body> ???<h1>自定义函数</h1> ???{{ww()|safe}}</body></html>

run.py

#!/usr/bin/env python# -*- coding:utf-8 -*-from flask import Flask,render_templateapp = Flask(__name__) ?def wupeiqi(): ???return ‘<h1>Wupeiqi</h1>‘ @app.route(‘/login‘, methods=[‘GET‘, ‘POST‘])def login(): ???return render_template(‘login.html‘, ww=wupeiqi) app.run()

请求和响应

复制代码 ??from flask import Flask ???from flask import request ???from flask import render_template ???from flask import redirect ???from flask import make_response ???app = Flask(__name__) ???@app.route(‘/login.html‘, methods=[‘GET‘, "POST"]) ???def login(): ???????# 请求相关信息 ???????# request.method ???????# request.args ???????# request.form ???????# request.values ???????# request.cookies ???????# request.headers ???????# request.path ???????# request.full_path ???????# request.script_root ???????# request.url ???????# request.base_url ???????# request.url_root ???????# request.host_url ???????# request.host ???????# request.files ???????# obj = request.files[‘the_file_name‘] ???????# obj.save(‘/var/www/uploads/‘ + secure_filename(f.filename)) ???????# 响应相关信息 ???????# return "字符串" ???????# return render_template(‘html模板路径‘,**{}) ???????# return redirect(‘/index.html‘) ???????# response = make_response(render_template(‘index.html‘)) ???????# response是flask.wrappers.Response类型 ???????# response.delete_cookie(‘key‘) ???????# response.set_cookie(‘key‘, ‘value‘) ???????# response.headers[‘X-Something‘] = ‘A value‘ ???????# return response ???????return "内容" ???if __name__ == ‘__main__‘: ???????app.run()

Session

除请求对象之外,还有一个 session 对象。它允许你在不同请求间存储特定用户的信息。它是在 Cookies 的基础上实现的,并且对 Cookies 进行密钥签名要使用会话,你需要设置一个密钥。

  • 设置:session[‘username‘] = ‘xxx‘

  • 删除:session.pop(‘username‘, None)

基本使用:

from flask import Flask, session, redirect, url_for, escape, request app = Flask(__name__) @app.route(‘/‘)def index(): ???if ‘username‘ in session: ???????return ‘Logged in as %s‘ % escape(session[‘username‘]) ???return ‘You are not logged in‘ @app.route(‘/login‘, methods=[‘GET‘, ‘POST‘])def login(): ???if request.method == ‘POST‘: ???????session[‘username‘] = request.form[‘username‘] ???????return redirect(url_for(‘index‘)) ???return ‘‘‘ ???????<form action="" method="post"> ???????????<p><input type=text name=username> ???????????<p><input type=submit value=Login> ???????</form> ???‘‘‘ @app.route(‘/logout‘)def logout(): ???# remove the username from the session if it‘s there ???session.pop(‘username‘, None) ???return redirect(url_for(‘index‘)) # set the secret key. ?keep this really secret:app.secret_key = ‘A0Zr98j/3yX R~XHH!jmN]LWX/,?RT‘

自定义session

pip3 install Flask-Session ???????????????run.py ???????????from flask import Flask ???????????from flask import session ???????????from pro_flask.utils.session import MySessionInterface ???????????app = Flask(__name__) ???????????app.secret_key = ‘A0Zr98j/3yX R~XHH!jmN]LWX/,?RT‘ ???????????app.session_interface = MySessionInterface() ???????????@app.route(‘/login.html‘, methods=[‘GET‘, "POST"]) ???????????def login(): ???????????????print(session) ???????????????session[‘user1‘] = ‘alex‘ ???????????????session[‘user2‘] = ‘alex‘ ???????????????del session[‘user2‘] ???????????????return "内容" ???????????if __name__ == ‘__main__‘: ???????????????app.run() ???????session.py ???????????#!/usr/bin/env python ???????????# -*- coding:utf-8 -*- ???????????import uuid ???????????import json ???????????from flask.sessions import SessionInterface ???????????from flask.sessions import SessionMixin ???????????from itsdangerous import Signer, BadSignature, want_bytes ???????????class MySession(dict, SessionMixin): ???????????????def __init__(self, initial=None, sid=None): ???????????????????self.sid = sid ???????????????????self.initial = initial ???????????????????super(MySession, self).__init__(initial or ()) ???????????????def __setitem__(self, key, value): ???????????????????super(MySession, self).__setitem__(key, value) ???????????????def __getitem__(self, item): ???????????????????return super(MySession, self).__getitem__(item) ???????????????def __delitem__(self, key): ???????????????????super(MySession, self).__delitem__(key) ???????????class MySessionInterface(SessionInterface): ???????????????session_class = MySession ???????????????container = {} ???????????????def __init__(self): ???????????????????import redis ???????????????????self.redis = redis.Redis() ???????????????def _generate_sid(self): ???????????????????return str(uuid.uuid4()) ???????????????def _get_signer(self, app): ???????????????????if not app.secret_key: ???????????????????????return None ???????????????????return Signer(app.secret_key, salt=‘flask-session‘, ?????????????????????????????????key_derivation=‘hmac‘) ???????????????def open_session(self, app, request): ???????????????????""" ???????????????????程序刚启动时执行,需要返回一个session对象 ???????????????????""" ???????????????????sid = request.cookies.get(app.session_cookie_name) ???????????????????if not sid: ???????????????????????sid = self._generate_sid() ???????????????????????return self.session_class(sid=sid) ???????????????????signer = self._get_signer(app) ???????????????????try: ???????????????????????sid_as_bytes = signer.unsign(sid) ???????????????????????sid = sid_as_bytes.decode() ???????????????????except BadSignature: ???????????????????????sid = self._generate_sid() ???????????????????????return self.session_class(sid=sid) ???????????????????# session保存在redis中 ???????????????????# val = self.redis.get(sid) ???????????????????# session保存在内存中 ???????????????????val = self.container.get(sid) ???????????????????if val is not None: ???????????????????????try: ???????????????????????????data = json.loads(val) ???????????????????????????return self.session_class(data, sid=sid) ???????????????????????except: ???????????????????????????return self.session_class(sid=sid) ???????????????????return self.session_class(sid=sid) ???????????????def save_session(self, app, session, response): ???????????????????""" ???????????????????程序结束前执行,可以保存session中所有的值 ???????????????????如: ???????????????????????保存到resit ???????????????????????写入到用户cookie ???????????????????""" ???????????????????domain = self.get_cookie_domain(app) ???????????????????path = self.get_cookie_path(app) ???????????????????httponly = self.get_cookie_httponly(app) ???????????????????secure = self.get_cookie_secure(app) ???????????????????expires = self.get_expiration_time(app, session) ???????????????????val = json.dumps(dict(session)) ???????????????????# session保存在redis中 ???????????????????# self.redis.setex(name=session.sid, value=val, time=app.permanent_session_lifetime) ???????????????????# session保存在内存中 ???????????????????self.container.setdefault(session.sid, val) ???????????????????session_id = self._get_signer(app).sign(want_bytes(session.sid)) ???????????????????response.set_cookie(app.session_cookie_name, session_id, ???????????????????????????????????????expires=expires, httponly=httponly, ???????????????????????????????????????domain=domain, path=path, secure=secure)自定义Session
View Code

message

message是一个基于Session实现的用于保存数据的集合,其特点是:使用一次就删除。

from flask import Flask, flash, redirect, render_template, request, get_flashed_messages ???????app = Flask(__name__) ???????app.secret_key = ‘some_secret‘ ???????@app.route(‘/‘) ???????def index1(): ???????????messages = get_flashed_messages() ???????????print(messages) ???????????return "Index1" ???????@app.route(‘/set‘) ???????def index2(): ???????????v = request.args.get(‘p‘) ???????????flash(v) ???????????return ‘ok‘ ???????if __name__ == "__main__": ???????????app.run()

中间件

from flask import Flask, flash, redirect, render_template, request app = Flask(__name__)app.secret_key = ‘some_secret‘ @app.route(‘/‘)def index1(): ???return render_template(‘index.html‘) @app.route(‘/set‘)def index2(): ???v = request.args.get(‘p‘) ???flash(v) ???return ‘ok‘ class MiddleWare: ???def __init__(self,wsgi_app): ???????self.wsgi_app = wsgi_app ????def __call__(self, *args, **kwargs): ????????return self.wsgi_app(*args, **kwargs) if __name__ == "__main__": ???app.wsgi_app = MiddleWare(app.wsgi_app) ???app.run(port=9999)

web框架之Flask

原文地址:http://www.cnblogs.com/Crazy-lyl/p/7758139.html

知识推荐

我的编程学习网——分享web前端后端开发技术知识。 垃圾信息处理邮箱 tousu563@163.com 网站地图
icp备案号 闽ICP备2023006418号-8 不良信息举报平台 互联网安全管理备案 Copyright 2023 www.wodecom.cn All Rights Reserved