0%

Web框架

Flask

为什么要用Web框架

WebFrame

Flask程序运行过程

  1. 客户端通过浏览器发送HTTP请求,请求获取资源
  2. Web服务器会把来自客户端的所有请求都交给Flask程序实例
  3. Flask程序实例通过Werkzeug来做路由分发URL请求和视图函数之间的对应关系

  4. 根据每个URL请求,找到具体的视图函数并进行调用

    • 在Flask程序中,路由的实现一般是通过程序实例的装饰器实现
  5. Flask调用视图函数后,可以返回两种内容
    • 字符串内容:将视图函数的返回值作为响应的内容,返回给客户端(浏览器)
    • HTML模版内容:获取到数据后,把数据传入HTML模版文件中,模版引擎负责渲染HTTP响应数据,然后返回响应数据给客户端(浏览器)
1
2
3
4
5
6
7
8
9
10
11
12
13
from flask import Flask

app = Flask(__name__)

# "/"代表一个URL请求;hello_world()是视图函数;
# 写在一起代表对应关系
@app.route("/", methods=["GET"])
def hello_world():
return "hello world"

if __name__ == "__main__":
# 执行run方法,将flask程序运行在简易服务器里(Flask提供)
app.run()

路由请求方式限定

1
2
3
@app.route("/orders/<int:orderid>", methods=["GET"])
def hello_world(orderid):
return "order id is %d" %orderid
  • 数据强转为int,能转成功,则可以进行路由匹配
  • 如果不能转成功,则无法进行路由匹配

Jinja2模版引擎

视图函数的主要作用是生成请求的响应,这是最简单的请求。实际上,视图函数有两个作用:处理业务逻辑和返回响应内容。在大型应用中,把业务逻辑和表现内容放在一起,会增加代码的复杂度和维护成本。利用模版,可以承担视图函数的另一个作用:返回响应内容。

使用模版的好处:

  • 视图函数只负责业务逻辑和数据处理(业务逻辑方面)
  • 模版则取到视图函数的数据结果进行展示(视图展示方面)
  • 代码结构清晰,耦合度低
1
2
3
4
5
6
7
8
9
10
11
12
13
14
from flask import Flask, render_template

app = Flask(__name__)

# 返回一个网页(模版)
# 给模版填充数据
@app.route("/", methods=["GET"])
def hello_world():
# 比如需要传入一个网址
url_str = '这里是动态传入的内容'
return render_template("index.html", url_str=url_str)

if __name__ == "__main__":
app.run()

在html中,动态的变量只需要以下方式写就可以进行定位了

1
{{ url_str }}

变量代码块

{{}}`来表示变量名,这种`{{}}语法叫做变量代码块

jinjia2模版中的变量代码块可以是任意python类型或者对象,只要它能够被Python的str()方法转为一个字符串就可以

1
2
{{your_dict['key']}}
{{your_list[0]}}

控制代码块

{%%}定义的控制代码块,可以实现一些语言层次的功能,比如循环或者if语句

1
2
3
4
5
6
7
8
{% if usr %}
{{ usr }}
{% else %}
hello!

{% for index in indexs %}
{{ index }}
{% endfor %}

过滤器

过滤器的本质就是函数,有时候我们不仅仅只需要输出变量的值,还需要修改变量的显示,甚至格式、运算符等等,而在模版中是不能直接调用Python中的某些方法,那么就用到了过滤器

  • 使用方法

过滤器的使用方法为:变量名 | 过滤器

1
{{variable | filter_name(*args)}}

如果没有任何参数传给过滤器,可以把括号省掉

1
{{variable | filter_name}}

如:’’,这个过滤器的作用:把变量variable的值的首字母转化为大写,其他字母转化为小写

  • 链式调用

在jinjia2中,过滤器是可以支持链式调用的

1
{{"hello world" | reverse | upper}}
  • 常见内置过滤器

    • 字符串操作

    禁用转义-safe、capitalize-首字母改大写、lower-小写、upper-大写、title-每个值改大写、truncate[i]-字符串截断

    • 列表操作

    first-取第一个、last-取最后一个、length-获取长度、sum-列表求和、sort-列表排序

    • 语句块过滤
    1
    2
    3
    {% filter upper %}
    一大堆文字
    {% endfilter %}

Python中三大框架各自的应用场景

  • django:主要是用来搞快速开发的,他的亮点就是快速开发,节约成本,如果要实现高并发的话,就要对django进行二次开发,比如把整个笨重的框架给拆掉自己写socket实现http的通信,底层用纯c,c++写提升效率,ORM框架给干掉,自己编写封装与数据库交互的框架, ORM虽然面向对象来操作数据库,但是它的效率很低,使用外键来联系表与表之间的查询;

  • flask: 轻量级,主要是用来写接口的一个框架,实现前后端分离,提高开发效率,Flask本身相当于一个内核,其他几乎所有的功能都要用到扩展(邮件扩展Flask-Mail,用户认证Flask-Login),都需要用第三方的扩展来实现。比如可以用Flask-extension加入ORM、文件上传、身份验证等。Flask没有默认使用的数据库,你可以选择MySQL,也可以用NoSQL。

    WSGI工具用Werkzeug(路由模块—负责路由转发)模板引擎则使用Jinja2,这两个也是Flask框架的核心。

  • Tornado: Tornado是一种Web服务器软件的开源版本。Tornado和现在的主流Web服务器框架(包括大多数Python的框架)有着明显的区别:它是非阻塞式服务器,而且速度相当快。得利于其非阻塞的方式和对epoll的运用,Tornado每秒可以处理数以千计的连接因此Tornado是实时Web服务的一个理想框架

对Flask蓝图(Blueprint)的理解?

  • 蓝图的定义

蓝图 /Blueprint 是Flask应用程序组件化的方法,可以在一个应用内或跨越多个项目共用蓝图。使用蓝图可以极大简化大型应用的开发难度,也为Flask扩展提供了一种在应用中注册服务的集中式机制。

  • 蓝图的应用场景:

把一个应用分解为一个蓝图的集合。这对大型应用是理想的。一个项目可以实例化一个应用对象,初始化几个扩展,并注册一集合的蓝图。

以URL前缀和/或子域名,在应用上注册一个蓝图。URL前缀/子域名中的参数即成为这个蓝图下的所有视图函数的共同的视图参数(默认情况下)
在一个应用中用不同的URL规则多次注册一个蓝图。

通过蓝图提供模板过滤器、静态文件、模板和其他功能。一个蓝图不一定要实现应用或视图函数。

初始化一个Flask扩展时,在这些情况中注册一个蓝图。

蓝图的缺点:

不能在应用创建后撤销注册一个蓝图而不销毁整个应用对象。

  • 使用蓝图的三个步骤

1.创建一个蓝图对象

1
blue = Blueprint("blue",__name__)

2.在这个蓝图对象上进行操作,例如注册路由、指定静态文件夹、注册模板过滤器…

1
2
3
@blue.route('/')
def blue_index():
return "Welcome to my blueprint"

3.在应用对象上注册这个蓝图对象

1
app.register_blueprint(blue,url_prefix="/blue")

Flask 和 Django 路由映射的区别?

在django中,路由是浏览器访问服务器时,先访问的项目中的url,再由项目中的url找到应用中url,这些url是放在一个列表里,遵从从前往后匹配的规则。

在flask中,路由是通过装饰器给每个视图函数提供的,而且根据请求方式的不同url用于不同的作用。

WSGI

WSGI(Web Server Gateway Interface)Web服务器网关接口,是Python应用程序或框架和Web服务器之间的一种接口,WSGI的其中一个目的就是让用户可以用统一的语言(Python)编写前后端。

它不是服务器,也不是python模块,它是一种规范,描述Web服务器和应用之间的交互.通俗来讲, 它就是一条纽带,连接着Web服务器和应用。

Django

Django程序运行过程

一般是用户通过浏览器向我们的服务器发起一个请求(request),这个请求会去访问视图函数,如果不涉及到数据调用,那么这个时候视图函数返回一个模板也就是一个网页给用户)
视图函数调用模型去数据库查找数据,然后逐级返回,视图函数把返回的数据填充到模板中空格中,最后返回网页给用户。

1.wsgi ,请求封装后交给web框架(Flask,Django)

2.中间件,对请求进行校验或在请求对象中添加其他相关数据,例如:csrf,request.session

3.路由匹配 根据浏览器发送的不同url去匹配不同的视图函数

4.视图函数,在视图函数中进行业务逻辑的处理,可能涉及到:orm,templates

5.中间件,对响应的数据进行处理

6.wsgi,将响应的内容发送给浏览器

wsgi,uwsgi,uWSGI?

WSGI:

web服务器网关接口,是一套协议。用于接收用户请求并将请求进行初次封装,然后将请求交给web框架

实现wsgi协议的模块:wsgiref, 本质上就是编写一socket服务端,用于接收用户请求(django)

werkzeug,本质上就是编写一个socket服务端,用于接收用户请求(flask)

uwsgi:

与WSGI一样是一种通信协议,它是uWSGI服务器的独占协议,用于定义传输信息的类型。

uWSGI:

是一个web服务器,实现了WSGI的协议,uWSGI协议,http协议

nginx,tomcat,apache都是什么?

  • Nginx(engine x)是一个高性能的HTTP和反向代理服务器,也是 一个IMAP/POP3/SMTP服务器,工作在OSI七层,负载的实现方式:轮询,IP_HASH,fair,session_sticky.

    nginx 是一个开源的高性能的HTTP服务器和反向代理

    1.作为web服务器,它处理静态文件和索引文件效果非常高

    2.它的设计非常注重效率,最大支持5万个并发连接,但只占用很少的内存空间

    3.稳定性高,配置简洁。

    4.强大的反向代理和负载均衡功能,平衡集群中各个服务器的负载压力应用

  • Apache HTTP Server是一个模块化的服务器,源于NCSAhttpd服务器

  • Tomcat 服务器是一个免费的开放源代码的Web应用服务器,属于轻量级应用服务器,是开发和调试JSP程序的首选。

Django、Flask、Tornado的对比?

1、 Django走的大而全的方向,重量级web框架,功能齐全,提供一站式解决的思路,能让开发者不用在选择上花费大量时间。

  • 自带ORM和模板引擎,支持jinja等非官方模板引擎。

自带ORM使Django和关系型数据库耦合度高,如果要使用非关系型数据库,需要使用第三方库。

  • 自带数据库管理app

成熟,稳定,开发效率高,相对于Flask,Django的整体封闭性比较好,适合做企业级网站的开发。python web框架的先驱,第三方库丰富

2、 Flask 是轻量级的框架,自由,灵活,可扩展性强,核心基于Werkzeug WSGI工具 和jinja2 模板引擎

适用于做小网站以及web服务的API,开发大型网站无压力,但架构需要自己设计

与关系型数据库的结合不弱于Django,而与非关系型数据库的耦合度高,远远优于Django

3、 Tornado走的是少而精的方向,性能优越,它最出名的异步非阻塞的设计方式

Tornado的两大核心模块:

iostraem:对非阻塞的socket进行简单的封装

ioloop: 对I/O 多路复用的封装,它实现一个单例

为什么要使用会话管理

众所周知,HTTP协议是一个无状态的协议,也就是说每个请求都是一个独立的请求,请求与请求之间并无关系。但在实际的应用场景,这种方式并不能满足我们的需求。举个大家都喜欢用的例子,把商品加入购物车,单独考虑这个请求,服务端并不知道这个商品是谁的,应该加入谁的购物车?因此这个请求的上下文环境实际上应该包含用户的相关信息,在每次用户发出请求时把这一小部分额外信息,也做为请求的一部分,这样服务端就可以根据上下文中的信息,针对具体的用户进行操作。所以这几种技术的出现都是对HTTP协议的一个补充,使得我们可以用HTTP协议+状态管理构建一个的面向用户的WEB应用。

Session 和Cookie的区别

这里我想先谈谈session与cookies,因为这两个技术是做为开发最为常见的。那么session与cookies的区别是什么?个人认为session与cookies最核心区别在于额外信息由谁来维护。利用cookies来实现会话管理时,用户的相关信息或者其他我们想要保持在每个请求中的信息,都是放在cookies中,而cookies是由客户端来保存,每当客户端发出新请求时,就会稍带上cookies,服务端会根据其中的信息进行操作。
当利用session来进行会话管理时,客户端实际上只存了一个由服务端发送的session_id,而由这个session_id,可以在服务端还原出所需要的所有状态信息,从这里可以看出这部分信息是由服务端来维护的。

除此以外,session与cookies都有一些自己的缺点:

cookies的安全性不好,攻击者可以通过获取本地cookies进行欺骗或者利用cookies进行CSRF攻击。使用cookies时, 在多个域名下,会存在跨域问题。
session 在一定的时间里,需要存放在服务端,因此当拥有大量用户时,也会大幅度降低服务端的性能,当有多台机器时,如何共享session也会是一个问题.(redis集群)也就是说,用户第一个访问的时候是服务器A,而第二个请求被转发给了服务器B,那服务器B如何得知其状态。实际上,session与cookies是有联系的,比如我们可以把session_id存放在cookies中的。

JWT是如何工作的

首先用户发出登录请求,服务端根据用户的登录请求进行匹配,如果匹配成功,将相关的信息放入payload中,利用算法,加上服务端的密钥生成token,这里需要注意的是secret_key很重要,如果这个泄露的话,客户端就可以随机篡改发送的额外信息,它是信息完整性的保证。生成token后服务端将其返回给客户端,客户端可以在下次请求时,将token一起交给服务端,一般是说我们可以将其放在Authorization首部中,这样也就可以避免跨域问题。

用的restframework完成api发送时间时区

当前的问题是用django的rest framework模块做一个get请求的发送时间以及时区信息的api

1
2
3
4
5
6
class getCurrenttime(APIView):
def get(self,request):
local_time = time.localtime()
time_zone =settings.TIME_ZONE
temp = {'localtime':local_time,'timezone':time_zone}
return Response(temp)

django中间件的使用?

Django在中间件中预置了六个方法,这六个方法的区别在于不同的阶段执行,对输入或输出进行干预,方法如下:

1.初始化:无需任何参数,服务器响应第一个请求的时候调用一次,用于确定是否启用当前中间件

1
2
def __init__():
pass

2.处理请求前:在每个请求上调用,返回None或HttpResponse对象。

1
2
def process_request(request):
pass

3.处理视图前:在每个请求上调用,返回None或HttpResponse对象。

1
2
def process_view(request,view_func,view_args,view_kwargs):
pass

4.处理模板响应前:在每个请求上调用,返回实现了render方法的响应对象。

1
2
def process_template_response(request,response):
pass

5.处理响应后:所有响应返回浏览器之前被调用,在每个请求上调用,返回HttpResponse对象。

1
2
def process_response(request,response):
pass

6.异常处理:当视图抛出异常时调用,在每个请求上调用,返回一个HttpResponse对象。

1
2
def process_exception(request,exception):
pass

Django中哪里用到了线程?哪里用到了协程?哪里用到了进程?

1.Django中耗时的任务用一个进程或者线程来执行,比如发邮件,使用celery.

2.部署django项目是时候,配置文件中设置了进程和协程的相关配置。

有用过Django REST framework吗?

Django REST framework是一个强大而灵活的Web API工具。使用RESTframework的理由有:

Web browsable API对开发者有极大的好处

包括OAuth1a和OAuth2的认证策略

支持ORM和非ORM数据资源的序列化

全程自定义开发—如果不想使用更加强大的功能,可仅仅使用常规的function-based views额外的文档和强大的社区支持