python3flask教程_python3 Flask基础知识详细讲解

知识回顾

1、django 和flask区别?

最大的不同就是django请求相关的数据,通过参数一个一个传递过去的,而flask就是先把放在某个地方,然后去取,这个东西叫上下文管理

2、什么是wsgi?

web服务网关接口,wsgi就是一个协议和规范,实现该协议的模块:

-wsgiref

-werkzeug

实现其协议的模块本质上就是socket服务端用于接收用户请求,并处理,

一般web框架基于wsgi实现,这样实现关注点分离(通俗的说业务相关的,交给框架)

from werkzeug.wrappers importResponsefrom werkzeug.serving importrun_simpledefrun_sever(environ,start_response):

response=Response('duoduo') #封装一下

returnresponse(environ,start_response)if __name__ == '__main__':

run_simple('127.0.0.1',8000,run_sever)

3、flask提供的功能

配置文件

所有配置文件都在flask的对象.config中

flask的对象.config.from_object('引入类的路径')   小写也是生效的

应用: importlib 、getattr

django中间件

rest framework全局配置

session

加密后放置在用户浏览器的cookie中

流程:

请求到来--------》视图函数---------》请求结束

配置文件   生命周期31天   加密设置

路由

带参数的装饰器,自定义装饰器放下面

常用url,methods,endpoint   反向 url_for

视图

FBV

特殊装饰器

before_first_request

before_request

after_request

template_global()

template_filter()

errorhandler(404)

请求和响应

请求:request

响应:四种 字符串、render_template(模板)、redirect、jsonify (序列化)

加响应头就make_response

一、路由和视图

from flask importFlask

duo=Flask(__name__)

@duo.route('/index')defindex():print('index')return 'Index'

if __name__ == '__main__':

duo.run()

我们今天开看看route的源码是什么样子的:

先不看中间的,发现定义阶段只是返回了 函数decorator的名字

1、限制性  decorator=duo.route('/index')

2、@decorator   这就和装饰器的原理一样,执行的话就把被装饰的函数名字传进去

3、上图中的f就是index函数,而rule就是(’/index‘)

这里就可以看出这个装饰器实质上就是:

duo.add_url_rule('/index', None, index)

我们注释掉装饰器,就用这一句代码跑跑看,脚本跑起来没问题!

我们继续看。add_url_rule里面的源码:

验证了之前说过的为什么endpoint默认情况等于函数名

获得参数都放到类似一个类,点开看看

果然是一个类

将路有关系添加到所有路由关系映射表

总结:

尽量不要让endpoint重名,如果重名函数一定要相同

参数:

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/', redirect_to='/home/')

def func(adapter, nid):

return "/home/888"

@app.route('/index/', redirect_to=func)

subdomain=None, 子域名访问

CBV:

from flask importFlask,viewsimportfunctoolsdefwrapper(func):

@functools.wraps(func)def inner(*args,**kwargs):return func(*args,**kwargs)returninner

duo=Flask(__name__)classUserView(views.MethodView):

methods= ['GET'] #只允许GET请求

decorators = [wrapper,] #加上要执行的装饰器的名字

def get(self,*args,**kwargs):return 'GET'

def post(self,*args,**kwargs):return 'POST'duo.add_url_rule('/user',None,UserView.as_view('uuuu'))if __name__ == '__main__':

duo.run()

基本上大同小异

自定义正则:

from flask importFlask,url_for

duo=Flask(__name__)#步骤一:定制类

from werkzeug.routing importBaseConverterclassRegexConverter(BaseConverter):'''自定义URL匹配正则表达式'''

def __init__(self,map,regex):

super(RegexConverter,self).__init__(map)

self.regex=regexdefto_python(self, value):'''路由匹配时,匹配成功过后传递给视图函数中参数的值

:param value:

:return:'''

returnint(value)defto_url(self, value):'''使用url_for反向生成URL时,传递的参数经过该方法处理,返回值用于生成URL中的参数

:param value:

:return:'''val=super(RegexConverter,self).to_url(value)return val #完全可以不写

#步骤二:添加到转换器duo.url_map.converters['reg']=RegexConverter'''1、用户发送请求

2、flask内部进行正则匹配

3、调用to_python(正则匹配的结果)方法

4、to_python的返回值会交给视图函数的参数'''

#步骤三:使用自定义正则

@duo.route('/index/')defindex(nid):print(nid,type(nid))print(url_for('index',nid=1))return 'index'

if __name__ == '__main__':

duo.run()

二、session实现原理(源码)

flask

下面我们来一行行来验证上面猜想的:

self 是Flask的对象duo,environ请求相关的原始数据

三、蓝图

目标:给开发者提供一个目录结构

1、首先创建一个和项目一样名字的文件夹,在文件夹中的__init__.py,先定义一个创建对象的函数

from flask importFlaskdefcreate_app():

duo=Flask(__name__)return duo

2、在项目一样名字的文件夹下,创建视图文件夹,在里面单独创建需求的功能视图

from flask importBlueprint

uc=Blueprint('ac',__name__)

@uc.route('/index/')defindex():return 'Index'

3、建立他们之间的关系,在__init__导入生成的对象 uc,最后注册进去

from flask importFlaskfrom .views.user importucdefcreate_app():

duo=Flask(__name__)

duo.register_blueprint(uc,url_prefix='/duoduuo') #url_prefix适用版本控制returnduo#最后再写一个运行的脚本,

其他的功能:

自定义模板、静态文件

某一类url添加前缀

某一类url添加before_request

四、threading.local(和flask无任何关系)

先看一个简单事例:

importthreadingimporttime

v=0deftask(i):globalv

v=i

time.sleep(1)print(v)for i in range(10):

t=threading.Thread(target=task,args=(i,))

t.start()#结果都是9,最后一个修改覆盖所有,解决方法加锁

看一种解决方案:

importthreadingfrom threading importlocal#为每给线程创建一个独立空间来修改数据,使得线程对自己的空间中的数据进行操作(数据隔离)

importtime

obj=local()deftask(i):

obj.duo=i

time.sleep(1)print(obj.duo,i)for i in range(10):

t=threading.Thread(target=task,args=(i,))

t.start()

现在我们来考虑几个问题,

如何获取一个线程的唯一标记 ?

threading.get_ident() #跟linux进程pid类似

根据字典自定义一个类似于threading.local功能?

通过getattr,setattr 构建出加强版的threading.local功能!

importtimeimportthreadingtry:import greenlet #有就是协程,没有就是线程

get_ident=greenlet.getcurrentexceptException as e:

get_ident=threading.get_identclassLocal(object):

DIC={}def __getattr__(self, item): #self.xxx 触发执行

#print('getattr',item)

ident=get_ident()if ident inself.DIC:returnself.DIC[ident].get(item)returnNonedef __setattr__(self, key, value): #self.xxx=123 触发执行

#print('setattr',key,value)

ident=get_ident()if ident inself.DIC:

self.DIC[ident][key]=valueelse:

self.DIC[ident]={key:value}

obj=Local()deftask(i):

obj.duo=i

time.sleep(1)print(obj.duo,i)for i in range(10):

t=threading.Thread(target=task,args=(i,))

t.start()

后续还是有看源码的博客:

五、简述上下文管理

1、当请求到来时,在源码中wsgi_app 中 ctx 对象是RequestContext封装所有的对象和请求相关的原始数据,

这个对象就有request和session,在接下来的对session进行补充,将包含了request/session的ctx对象放到’神奇的地方‘

这个神奇的地方就是一个大字典,用线程或协程的唯一标识为key,

2、当视图函数使用的时候:

假使取一个request.method  ,我们先导入 from  flask import request ,根据当前线程取ctx对象,再取request,再取.method

3、当请求结束:

根据当前线程的唯一标记,将’神奇地方‘上的数据移除

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值