前言
本文意在了解Flask的基本概念,想要清楚知道Flask和Django的区别,以下是具体的区别
Flask和Django有什么区别?
- Flask
- 轻量级web框架,默认依赖两个外部库:jinja2和Werkzeug WSGI工具
- 适用于做小型网站以及web服务的API,开发大型网站无压力,但架构需要自己设计
- 与关系型数据库的结合相当Django,而与非关系型数据库的结合远远优于Django
-
Django
- 重量级web框架,功能齐全,提供一站式解决的思路,能让开发者不用在选择上花费大量时间。
- 自带ORM(Object-Relational Mapping 对象关系映射)和模板引擎,支持jinja等非官方模板引擎。
- 自带ORM使Django和关系型数据库耦合度高,如果要使用非关系型数据库,需要使用第三方
- 自带数据库管理app
- 成熟,稳定,开发效率高,相对于Flask,Django的整体封闭性比较好,适合做企业级网站的开发。
- python web框架的先驱,第三方库丰富
环境
系统环境
Distributor ID: Deepin
Description: Deepin 20 Beta
Release: 20 Beta
Codename: n/a
Linux version : 5.3.0-3-amd64 (debian-kernel@lists.debian.org)
Gcc version: 8.3.0 (Debian 8.3.0-6)
Debian Version 10.4
软件信息
version :
None
正文
什么是Flask,有什么优点?
- 概念解释
Flask是一个Web框架,就是提供一个工具,库和技术来允许你构建一个Web应用程序。
这个Web应用程序可以是一些Web页面,博客,wiki,基于Web的日里应用或商业网站。
- 优点
Flask属于微框架(micro-framework)这一类别,微架构通常是很小的不依赖外部库的框架。
- 更新时依赖小
- 框架很轻量
- 专注于安全方面的bug
- Flask基本依赖
-
Werkzeug 一个WSGI工具包(web服务网关接口(Python Web Server Gateway Interface,缩写为WSGI)是为python语言定义的web服务器和web应用程序或框架之间的一种简单而通用的借口,其他语言也有类似的接口)
-
jinja2模板引擎
什么是WSGI?
WSGI(Web Server Gateway Interface,Web 服务器网关接口)则是Python语言中所定义的Web服务器和Web应用程序之间或框架之间的通用接口标准。
Werkzeug本质是Socket服务端,其用于接收http请求并对请求进行预处理,然后触发Flask框架。
WSGI就是一座桥梁,桥梁的一端称为服务端或网关端,另一端称为应用端或者框架端,WSGI的作用就是在协议之间进行转化。
WSGI将Web组件分成了三类:Web 服务器(WSGI Server)、Web中间件(WSGI Middleware)与Web应用程序(WSGI Application)。 Web Server接收HTTP请求,封装一系列环境变量,按照WSGI接口标准调用注册的WSGI Application,最后将响应返回给客户端。
Flask框架依赖组件?
- Route(路由)
- blueprint(蓝图)
- Models(orm模型)
- templates(模板)
列举使用过的Flask第三方组件?
flask_bootstrap
flask-WTF
flask_sqlalchemy
整体
Flask:MVC模型
flask是一个典型的MVC框架
- 浏览器请求get或者post
- 通过WSGI的装饰器route()路由重定向到指定的函数做指定的动作
- jinja2的render_template()渲染显示模板并输出
Flask脚本的常用方式是什么?
在shell中运行脚本文件
在python编译器中run
Flask应用实例化发生什么?
Flask应用的app.run()方法会调用werkzeug.serving模块中的run_simple方法。这个方法会创建一个本地的测试服务器,并且在这个服务器中运行Flask应用。
from werkzeug.wrappers import Request, Response
@Request.application
def hello(request):
return Response('Hello World!')
if __name__ == '__main__':
from werkzeug.serving import run_simple
run_simple('localhost', 4000, hello)
当服务器开始调用Flask应用后,便会触发Flask应用的_call_(environ, start_response)方法。其中environ由服务器产生,start_response在服务器中定义。
def __call__(self, environ, start_response):
"""The WSGI server calls the Flask application object as the
WSGI application. This calls :meth:`wsgi_app` which can be
wrapped to applying middleware."""
return self.wsgi_app(environ, start_response)
执行wsgi_app 得到 一个 RequestContext的对象 ctx (封装了request以及session)
上面我们分析到当Flask应用被调用时会执行wsgi_app(environ, start_response)方法。可以看出,wsgi_app是真正被调用的WSGI应用,之所以这样设计,就是为了在应用正式处理请求之前,wsgi_app可以被一些“中间件”装饰,以便先行处理一些操作。
简述Flask上下文管理流程?
每次有请求过来的时候,flask 会先创建当前线程或者进程需要处理的两个重要上下文对象,把它们保存到隔离的栈里面,这样视图函数进行处理的时候就能直接从栈上获取这些信息。
flask 提供两种上下文:application context 和 request context 。
application context 演化出来两个变量 current_app 和 g
request context 则演化出来 request 和 session。
想要搞清楚三个概念:
partial 偏函数 ,生成一个新的函数
local线程安全,保证线程安全,也保证了处理速度,保存一个全局变量,但是这个全局变量只有在当前线程才能访问
falsk上下文管理可以分为三个阶段:
1. 请求上文 ->
当请求进来,第一件事就是要把当前这个请求在服务器上的线程开辟一个空间(线程对应的空间,必须含有stack对应一个列表存放ctx(request/session).
具体-->: 将request,session封装在 RequestContext类中
将current_app,g封装在AppContext类中,
并通过LocalStack将requestcontext和appcontext放入Local类中
在local类中,以线程ID号作为key的字典.
2. 请求下文:
通过localproxy--->偏函数--->localstack--->local取值
3. '请求响应时':-->要将上下文管理中的数据清除
先执行save.session()再各自执行pop(),将local中的数据清除
请求
列举Http请求中常见的请求方式?
GET / POST/DELETE
列举HttpX响应中的状态码?
- 404 请求的url地址不存在
- 400 请求参数错误
- 503 访问限制有权限
- 201 请求成功,参数作进一步处理
- 200 访问成功
- 302 重定向
列举Http请求中常见的请求头?
User-Agent:浏览器类型,如果Servlet返回的内容与浏览器类型有关则该值非常有用。
Cookie:这是最重要的请求头信息之一
Content-Type:请求类型
Flask蓝图的作用?
蓝图Blueprint实现模块化的应用
-
book_bp = Blueprint(‘book’, name)创建蓝图对象
-
蓝图中使用路由@book_bp.route(‘url’)
-
在另一.py文件里导入和注册蓝图
from book import book_bp app.register_blueprint(book_bp)
作用
- 将不同的功能模块化
- 构建大型应用
- 优化项目结构
- 增强可读性,易于维护(跟Django的view功能相似)
如何在Flask中访问会话?
会话(seesion)会话数据存储在服务器上。 会话是客户端登录到服务器并注销的时间间隔。 需要在此会话中进行的数据存储在服务器上的临时目录中。
from flask import session导入会话对象
session['name'] = 'admin'给会话添加变量
session.pop('username', None)删除会话的变量
Flask框架默认session处理机制?
Flask的默认session利用了Werkzeug的SecureCookie,把信息做序列化(pickle)后编码(base64),放到cookie里了。
过期时间是通过cookie的过期时间实现的。
为了防止cookie内容被篡改,session会自动打上一个叫session的hash串,这个串是经过session内容、SECRET_KEY计算出来的,看得出,这种设计虽然不能保证session里的内容不泄露,但至少防止了不被篡改
谈谈flask-restful?
flask-restuful继承Rest架构
Rest架构的主要原则
** 网络上的所有事物都被抽象为资源**
** 每个资源都有一个唯一的资源标识符**
** 同一个资源具有多种表现形式(xml,json等)**
** 对资源的各种操作不会改变资源标识符**
** 所有的操作都是无状态的**
** 符合REST原则的架构方式即可称为RESTful**
解释:
1)URI(统一资源标识符):每一个URI代表一种资源,restful接口对资源进行增删改查
2) 客户端和服务器之间,传递这种资源的某种表现层
3)客户端通过四个HTTP动词(get、post、put、delete),对服务器资源进行操作,实现“表现层状态转化”
Method | CRUD |
---|---|
POST | Create(update,delete) |
GET | Read |
PUT | Update(create) |
DELETE | Delete |
也就是跟通过WSGI的装饰器route()路由重定向到指定的函数做指定的动作
原理类似
Flask-WTF是什么,有什么特点?
Flask-WTF是集成WTForms,并带有 csrf 令牌的安全表单和全局的 csrf 保护的功能。
每次我们在建立表单所创建的类都是继承与flask_wtf中的FlaskForm,
而FlaskForm是继承WTForms中forms。
Flask-WTF底层是调用WTForms,WTForms是一个支持多个web框架的form组件,主要用于对用户请求数据进行验证。
Flask-wtf是一个用于表单处理,校验并提供csrf(Cross SIte Request Forgery)验证的功能的扩展库 Flask-wtf能把正表单免受CSRF<跨站请求伪造>的攻击,[什么是CSRF](https://blog.csdn.net/wireless911/article/details/81589202)跨站请求伪造>
-
使用csrf_token校验
客户端和浏览器向后端发送请求时,后端往往会在响应中的 cookie 设置 csrf_token 的值,可以使用请求钩子实现,在cookie中设置csrf_token
flask_wtf 中为我们提供了CSRF保护,可以直接调用开启对app的保护
设置秘钥:SECRET_KEY
-
scrf验证
- 获取到 表单中/请求头中 的csrf_token(加密的),使用secret_key进行解密,得到解密后的csrf_token
- 通过cookie中的sessionID,取到服务器内部存储的session中的csrf_token(未加密的)
- 将解密后的csrf_token和服务器存储的csrf_token两个值进行比较
-
eg: wtf_form.html
<form action="" method='post'>
#进入csrf验证
<p></p>
<p></p>
<p></p>
</form>
manage.py
from flask import Flask,render_template,request
from flask_wtf import FlaskForm #导入继承父类
from wtforms import StringField,PasswordField,SubmitField
from wtforms.validators import Length,DataRequired
class Login(FlaskForm): #继承自FlaskForm类
username = StringField('用户名',validators=[Length(min=6,max=12,message='用户名长度为6~12位'),DataRequired(message='用户名不能为空')])
userpass = PasswordField('密码',validators=[Length(min=6,max=12,message='密码长度为6~12位'),DataRequired(message='密码不能为空')])
submit = SubmitField('登录')
@app.route('/wtf_form',methods=['GET','POST'])
def wtf_form():
form = Login() #实例化form对象
if request.method == 'POST':
if form.validate_on_submit(): #数据正确 并且验证csrf通过
print(request.form.get('userpass'))
print(request.form.get('username'))
return '数据提交成功'
return render_template('wtf_form.html',form=form)
#注:
#1 methods 参数告诉Flask在URL映射中把这个视图函数注册为GET和POST请求的处理程序,默认GET
#2 采用post请求可以通过对象很轻松访问,GET 请求没有主体,提交的数据以查询字符串的形式附加到URL中
#3 validate_on_submit() 会调用username 字段上附属的 DataRequired() 验证函数。
数据库
解释Python Flask中的数据库连接?
python中的数据库连接有两种方式
- 在脚本中以用第三方库正常连接,用sql语句正常操作数据库,如mysql关系型数据库的pymsql库
- 用ORM来进行数据库连接,flask中典型的flask_sqlalchemy,已面向对象的方式进行数据库的连接与操作
ORM的实现原理
概念: 对象关系映射(Object Relational Mapping,简称ORM,或O/RM,或O/R mapping),是一种程序技术,用于实现面向对象编程语言里不同类型系统的数据之间的转换。
详细介绍: 让我们从O/R开始。字母O起源于”对象”(Object),而R则来自于”关系”(Relational)。几乎所有的程序里面,都存在对象和关系数据库。在业务逻辑层和用户界面层中,我们是面向对象的。当对象信息发生变化的时候,我们需要把对象的信息保存在关系数据库中。 当你开发一个应用程序的时候(不使用O/R Mapping),你可能会写不少数据访问层的代码,用来从数据库保存,删除,读取对象信息,等等。你在DAL中写了很多的方法来读取对象数据,改变状态对象等等任务。而这些代码写起来总是重复的。
ORM解决的主要问题是对象关系的映射。域模型和关系模型分别是建立在概念模型的基础上的。域模型是面向对象的,而关系模型是面向关系的。一般情况下,一个持久化类和一个表对应,类的每个实例对应表中的一条记录,类的每个属性对应表的每个字段。
ORM技术特点:
- 提高了开发效率。由于ORM可以自动对Entity对象与数据库中的Table进行字段与属性的映射,所以我们实际可能已经不需要一个专用的、庞大的数据访问层。
- ORM提供了对数据库的映射,不用sql直接编码,能够像操作对象一样从数据库获取数据。