当前位置:   article > 正文

Python Flask 微型web服务_python flask 微服务

python flask 微服务

一、介绍

Flask是Python一个轻量级的web服务框架,只提供了web框架基本的功能,作为小型项目服务端。

二、环境

Python 3.7

Flask 1.1.1

三、安装

pip install flask

四、使用

(一)概念理解

  • 路由:Flask 根据 HTTP 请求的url,在路由表中匹配定义好的路由规则,找到对应的函数处理请求。在这个过程中需要保存一个url到行数的映射关系,我们把处理url到函数之间的关系成为路由,flask中的路由是使用装饰器的形式定义的,并且必须是/开头,否则报错。
  • 视图函数:视图函数是处理用户的请求,返回响应的函数代码块在Flask中视图函数的名字不能重复。
  • url路径参数(动态路由):可以通过请求的url中获取需要的参数。
  • 启动参数:

    run启动参数

    说明

    host

    主机地址,默认是127.0.0.1,运行外部ip地址访问,0.0.0.0

    port

    端口号,默认是5000

    debug

    调试模式,默认为false,开发的时候一般设置为true,这样有视图有错误,在浏览器中显示,方便调试错误。项目上线需要改为false。也可以启动重启代码。

    use_reloader

    是否自动重启代码,默认为false,true为自定义

(二)定义路由接口

1.run.py

  1. #!/usr/bin/python3
  2. # -*- coding: UTF-8 -*-
  3. import flask
  4. # 实例化
  5. app=flask.Flask(__name__)
  6. # 修饰器定义路由
  7. @app.route('/')
  8. # 每个路由对应一个函数(路由映射函数)
  9. def home():
  10. return {"msg":"success","status":200,"data":"成功"}
  11. if __name__=="__main__":
  12. app.debug = True # 设置调试模式,生产模式的时候要关掉debug
  13. app.run() # 启动程序

这是flask框架制作的一个最小的应用,使用python命令运行run.py后访问localhost:5000。

 

(三)请求格式

1.form

2.json

3.get url 参数

  1. @app.route('/user/<u_id>')
  2. def user_info(u_id):
  3. return {
  4. "msg": "success",
  5. "data": {
  6. "id": u_id,
  7. "username": 'yuz',
  8. "age": 18
  9. }
  10. }
  1. from flask import Flask,url_for,request,render_template
  2. @app.route('/login', methods=['POST', 'GET'])
  3. def login():
  4. # 获取请求方法
  5. if request.method == 'POST':
  6. # 获取请求body form
  7. if request.form['user'] == 'admin':
  8. return 'Admin login successfully!'
  9. else:
  10. return 'No such user!'
  11. title = request.args.get('title', 'Default')
  12. # 返回视图模板给客户端浏览器
  13. return render_template('login.html', title=title)
  14. if __name__ == "__main__":
  15. app.run(debug=True)

①request中”method”变量可以获取当前请求的方法,即”GET”, “POST”, “DELETE”, “PUT”等。

②"form"变量是一个字典,可以获取Post请求表单中的内容,在上例中,如果提交的表单中不存在"user"项,则会返回一个KeyError,你可以不捕获,页面会返回400错误(想避免抛出这"KeyError",你可以用request.form.get("user")来替代)。

③而"request.args.get()"方法则可以获取Get请求URL中的参数,该函数的第二个参数是默认值,当URL参数不存在时,则返回默认值。

4.文件上传

https://zhuanlan.zhihu.com/p/70957022?from_voters_page=true

flask 文件上传(单文件上传、多文件上传)-- - 夏晓旭 - 博客园

(四)响应内容

构建响应

  1. from flask import Flask,url_for,request,render_template,redirect,session,make_response
  2. @app.route('/login', methods=['POST', 'GET'])
  3. def login():
  4. if request.method == 'POST':
  5. ...
  6. if 'user' in session:
  7. ...
  8. else:
  9. title = request.args.get('title', 'Default')
  10. # 构建响应
  11. response = make_response(render_template('login.html', title=title), 200)# make_response方法就是用来构建response对象
  12. response.headers['key'] = 'value'
  13. return response
  14. if __name__ == "__main__":
  15. app.run(debug=True)

1.返回模板视图

Flask的模板功能是基于Jinja2模板引擎实现.

  1. from flask import Flask
  2. from flask import render_template
  3. app = Flask(__name__)
  4. @app.route('/home')
  5. @app.route('/home/<name>')
  6. def home(name=None):
  7. return render_template('home.html', name=name)
  8. if __name__ == '__main__':
  9. app.run(host='0.0.0.0', debug=True)

home()函数并不是直接返回字符串,而是调用了render_template()方法来渲染模板。

render_template()方法参数

方法的第一个参数home.html指向你想渲染的模板名称;

方法的第二个参数name是你要传到模板去的变量,变量可以传多个。

所有模板页面内容都放置在teamplate文件夹下。

home.html

  1. <!doctype html>
  2. <title>Hello Flask Sample demo</title>
  3. {% if name %}
  4. <h1>Hello {{ name }}!</h1>
  5. {% else %}
  6. <h1>Hello World!</h1>
  7. {% endif %}

它就是一个HTML模板,根据”name”变量的值,显示不同的内容。

变量或表达式由”{{ }}”修饰,而控制语句由”{% %}”修饰,其他的代码,就是我们常见的HTML。

让我们打开浏览器,输入”http://localhost:5000/hello/man”,页面上即显示大标题”Hello man!”。

接触过模板引擎就比较好理解,和nodejs express 一样。

Flask模板引擎使用Jinja2

Jinja2的模板引擎还有更多强大的功能,包括for循环,过滤器等。

模板里也可以直接访问内置对象如request, session等。

https://pypi.org/project/Jinja2/

Flask的Jinja2模板支持模板继承功能,省去了这些重复代码。

让我们基于上面的例子,在”templates”目录下,创建一个名为”layout.html”的模板:

  1. <!doctype html>
  2. <title>Hello Sample</title>
  3. <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='style.css') }}">
  4. <div class="page">
  5. {% block body %}
  6. {% endblock %}
  7. </div>

再修改之前的”home.html”,把原来的代码定义在”block body”中,并在代码一开始”继承”上面的”layout.html”:

  1. <!doctype html>
  2. <title>Hello Flask Sample demo</title>
  3. {% extends "layout.html" %}
  4. {% block body %}
  5. {% if name %}
  6. <h1>Hello {{ name }}!</h1>
  7. {% else %}
  8. <h1>Hello World!</h1>
  9. {% endif %}
  10. {% endblock %}

重新访问http://127.0.0.1:5000/

render_template() 加载了”home.html”模板,但是”layout.html”的内容也一起被加载了。

而且”home.html”中的内容被放置在”layout.html”中”{% block body %}”的位置上。

形象的说,就是”home.html”继承了”layout.html”。

2.返回字符串

3.返回json

  1. @app.route('/')
  2. # 每个路由对应一个函数(路由映射函数)
  3. def home():
  4. return {"msg": "success", "status": 200, "data": "成功"}

(五)会话session

会话可以用来保存当前请求的一些状态,以便于在请求之前共享信息。

  1. from flask import Flask,url_for,request,render_template,redirect,session,make_response
  2. # 登录接口
  3. @app.route('/login', methods=['POST', 'GET'])
  4. def login():
  5. # 获取客户端请求方法
  6. if request.method == 'POST':
  7. # 获取客户端请求body form
  8. if request.form['user'] == 'admin':
  9. # 设置一个session
  10. session['user'] = request.form['user']
  11. # 返回字符串给客户端浏览器
  12. return 'Admin login successfully!'
  13. else:
  14. return 'No such user!'
  15. # 判断用户是否已有session
  16. if 'user' in session:
  17. return 'Hello %s!' % session['user']
  18. else:
  19. # 没有则,获取客户端请求url参数
  20. title = request.args.get('title', 'Default')
  21. # 参数传给视图模板,并返回给客户端
  22. return render_template('login.html', title=title)
  23. # 退出接口
  24. @app.route('/logout')
  25. def logout():
  26. # 删除session
  27. session.pop('user', None)
  28. # 返回一个重定url向给客户端,且重定向url路由是登录登录接口
  29. return redirect(url_for('login'))
  30. # session秘钥设置
  31. app.secret_key = '123456'
  32. #
  33. if __name__ == "__main__":
  34. app.run(debug=True)

”admin”登陆成功后,再打开”login”页面就不会出现表单了,然后打开logout页面可以登出。

session对象的操作就跟一个字典一样,使用session时一定要设置一个密钥app.secret_key,否则会得到一个运行时错误,内容大致是”RuntimeError: the session is unavailable because no secret key was set”。

密钥要尽量复杂,比如一个随机数。

(六)cookie

cookie是客户端概念,存储在浏览器中

  1. from flask import Flask,url_for,request,render_template,redirect,session,make_response
  2. import time
  3. # 定义登录接口,支持两种方法
  4. @app.route('/login', methods=['POST', 'GET'])
  5. def login():
  6. response = None
  7. if request.method == 'POST':
  8. if request.form['user'] == 'admin':
  9. session['user'] = request.form['user']
  10. response = make_response('Admin login successfully!')
  11. # 设置响应body中setcookie
  12. response.set_cookie('login_time', time.strftime('%Y-%m-%d %H:%M:%S'))
  13. ...
  14. else:
  15. # 已存在该用户session
  16. if 'user' in session:
  17. # 判断客户端请求cookie中字段login_time
  18. login_time = request.cookies.get('login_time')
  19. #构建响应
  20. response = make_response('Hello %s, you logged in on %s' % (session['user'], login_time))
  21. ...
  22. return response
  23. # 秘钥
  24. app.secret_key = '123456'
  25. if __name__ == "__main__":
  26. app.run(debug=True)

引入了time模块来获取当前系统时间。

在返回响应时,通过response.set_cookie()”函数,来设置Cookie项,之后这个项值会被保存在浏览器中。

这个函数的第三个参数max_age可以设置该Cookie项的有效期,单位是秒,不设的话,在浏览器关闭后,该Cookie项即失效。

在请求中,request.cookies对象就是一个保存了浏览器Cookie的字典,使用其get()函数就可以获取相应的键值。

七、错误处理

使用abort()函数可以直接退出请求,返回错误代码

  1. from flask import Flask,abort
  2. app = Flask(__name__)
  3. # 定义404接口
  4. @app.route('/error')
  5. def error():
  6. # 中断
  7. abort(404)
  8. if __name__ == "__main__":
  9. app.run(debug=True)

上例会显示浏览器的404错误页面。

有时候,我们想要在遇到特定错误代码时做些事情,或者重写错误页面,可以用下面的方法:

  1. from flask import Flask,abort
  2. app = Flask(__name__)
  3. @app.errorhandler(404)
  4. def page_not_found(error):
  5. return render_template('404.html'), 404
  6. if __name__ == "__main__":
  7. app.run(debug=True)

在实际开发过程中,我们并不会经常使用abort()来退出,常用的错误处理方法一般都是异常的抛出或捕获。

而是用装饰器@app.errorhandler(),除了可以注册错误代码外,还可以注册指定的异常类型。

让我们来自定义一个异常:

  1. class InvalidUsage(Exception):# 继承父类Exception
  2. status_code = 400
  3. def __init__(self, message, status_code=400):
  4. # 调用基类构造函数
  5. Exception.__init__(self)
  6. # 接收类实例化入参
  7. self.message = message
  8. self.status_code = status_code
  9. @app.errorhandler(InvalidUsage)
  10. def invalid_usage(error):
  11. # 构造响应 返回错误异常内容给客户端
  12. response = make_response(error.message)
  13. # 响应状态码
  14. response.status_code = error.status_code
  15. return response
  16. @app.route('/exception')
  17. def exception():
  18. # 抛出异常
  19. raise InvalidUsage('No privilege to access the resource', status_code=403)
  20. if __name__ == "__main__":
  21. app.run(debug=True)

①我们在上面的代码中定义了一个异常InvalidUsage

②同时我们通过装饰器@app.errorhandler()修饰了函数invalid_usage(),装饰器中注册了我们刚定义的异常类。

③一但遇到InvalidUsage异常被抛出,这个invalid_usage()函数就会被调用。

八、url重定向

Flask的URL规则是基于Werkzeug的路由模块。

  1. @app.route('/projects/')
  2. def projects():
  3. return 'The project page'
  4. @app.route('/about')
  5. def about():
  6. return 'The about page'

访问第一个路由不带/时,Flask会自动重定向到正确地址。

访问第二个路由时末尾带上/后Flask会直接报404 NOT FOUND错误。

重定向”redirect()”函数的使用在上面例子中已有出现。

作用就是当客户端浏览某个网址时,将其导向到另一个网址。

常见的例子,比如:用户在未登录时浏览某个需授权的页面,我们将其重定向到登录页要求其登录先。

  1. from flask import session, redirect
  2. @app.route('/')
  3. def index():
  4. # 服务端判断用户会话是否存在
  5. if 'user' in session:
  6. return 'Hello %s!' % session['user']
  7. else:
  8. # 重定向到登录接口(登录接口会返回登录视图模板)并状态码为302
  9. return redirect(url_for('login'), 302)

redirect()第二个参数时HTTP状态码,值有301, 302, 303, 305和307,默认即302

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/185735
推荐阅读
相关标签
  

闽ICP备14008679号