python框架-Flask初探二

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_27695659/article/details/88739733

1. 路由和视图

a. 路由设置的两种方式:

			@app.route('/xxx')
				def index():
					return "index"

			
			def index():
				return "index"
			app.add_url_rule("/xxx",None,index)
			
			注意事项:
				- 不用让endpoint重名
				- 如果重名函数也一定要相同。

b. 参数

			rule,                       URL规则
			view_func,                  视图函数名称
			endpoint=None,              名称,用于反向生成URL,即: url_for('名称')
			methods=None,               允许的请求方式,如:["GET","POST"]
			strict_slashes=None,        对URL最后的 / 符号是否严格要求,
			redirect_to=None,           重定向到指定地址

			defaults=None,              默认值,当URL中无参数,函数需要参数时,使用defaults={'k':'v'}为函数提供参数
			subdomain=None,             子域名访问

c. CBV

			import functools
			from flask import Flask,views
			app = Flask(__name__)


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

				return inner



			class UserView(views.MethodView):
				methods = ['GET']
				decorators = [wrapper,]

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

				def post(self,*args,**kwargs):
					return 'POST'

			app.add_url_rule('/user',None,UserView.as_view('uuuu'))

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

d. 自定义正则

			from flask import Flask,url_for

			app = Flask(__name__)

			# 步骤一:定制类
			from werkzeug.routing import BaseConverter
			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

			# 步骤二:添加到转换器
			app.url_map.converters['reg'] = RegexConverter

			"""
			1. 用户发送请求
			2. flask内部进行正则匹配
			3. 调用to_python(正则匹配的结果)方法
			4. to_python方法的返回值会交给视图函数的参数

			"""

			# 步骤三:使用自定义正则
			@app.route('/index/<reg("\d+"):nid>')
			def index(nid):
				print(nid,type(nid))

				print(url_for('index',nid=987))
				return "index"

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

2. session实现原理(源码)

在这里插入图片描述

3. 蓝图

目标:给开发者提供目录结构
其他:

  • 自定义模板、静态文件
  • 某一类url添加前缀
  • 给一类url添加before_request

4. threading.local【和flask无任何关系】

作用:为每个线程创建一个独立的空间,使得线程对自己的空间中的数据进行操作(数据隔离)。

			import threading
			from threading import local
			import time

			obj = local()


			def task(i):
				obj.xxxxx = i
				time.sleep(2)
				print(obj.test,i)

			for i in range(10):
				t = threading.Thread(target=task,args=(i,))
				t.start()

问题:

  • 如何获取一个线程的唯一标记? threading.get_ident()
  • 根据字典自定义一个类似于threading.local功能?
				import time
				import threading

				DIC = {}

				def task(i):
					ident = threading.get_ident()
					if ident in DIC:
						DIC[ident]['test'] = i
					else:
						DIC[ident] = {'test':i }
					time.sleep(2)

					print(DIC[ident]['test'],i)

				for i in range(10):
					t = threading.Thread(target=task,args=(i,))
					t.start()
  • 根据字典自定义一个为每个协程开辟空间进行存取数据。
				import time
				import threading
				import greenlet

				DIC = {}

				def task(i):
					
					# ident = threading.get_ident()
					ident = greenlet.getcurrent()
					if ident in DIC:
						DIC[ident]['test'] = i
					else:
						DIC[ident] = {'test':i }
					time.sleep(2)

					print(DIC[ident]['test'],i)

				for i in range(10):
					t = threading.Thread(target=task,args=(i,))
					t.start()
  • 通过getattr/setattr 构造出来 threading.local的加强版(协程)
				import time
				import threading
				try:
					import greenlet
					get_ident =  greenlet.getcurrent
				except Exception as e:
					get_ident = threading.get_ident

				class Local(object):
					DIC = {}

					def __getattr__(self, item):
						ident = get_ident()
						if ident in self.DIC:
							return self.DIC[ident].get(item)
						return None

					def __setattr__(self, key, value):
						ident = get_ident()
						if ident in self.DIC:
							self.DIC[ident][key] = value
						else:
							self.DIC[ident] = {key:value}
						

				obj = Local()

				def task(i):
					obj.test = i
					time.sleep(2)
					print(obj.test,i)

				for i in range(10):
					t = threading.Thread(target=task,args=(i,))
					t.start()
  • 应用
    • Flask上下文管理中的Local类更高级
    • DBUtils线程池的模式一:为每个线程创建一个连接。
    • SQLAlchemy
					from sqlalchemy.orm import sessionmaker
					from sqlalchemy import create_engine
					from sqlalchemy.orm import scoped_session
					from models import Student,Course,Student2Course

					engine = create_engine(
							"mysql+pymysql://root:[email protected]:3306/s9day120?charset=utf8",
							max_overflow=0,  # 超过连接池大小外最多创建的连接
							pool_size=5,  # 连接池大小
							pool_timeout=30,  # 池中没有线程最多等待的时间,否则报错
							pool_recycle=-1  # 多久之后对线程池中的线程进行一次连接的回收(重置)
						)
					SessionFactory = sessionmaker(bind=engine)
					
					# 为每个线程创建一个连接 
					session = scoped_session(SessionFactory)


					def task():
						ret = session.query(Student).all()
						# 将连接交还给连接池
						session.remove()


					from threading import Thread

					for i in range(20):
						t = Thread(target=task)
						t.start()	

5. 上下文管理

请求到来时候:

		# ctx = RequestContext(self, environ) # self是app对象,environ请求相关的原始数据
		# ctx.request = Request(environ)
		# ctx.session = None
		
		# 将包含了request/session的ctx对象放到“空调”
			{
				1232:{ctx:ctx对象}
				1231:{ctx:ctx对象}
				1211:{ctx:ctx对象}
				1111:{ctx:ctx对象}
				1261:{ctx:ctx对象}
			}

视图函数:

		from flask import reuqest,session 
		
		request.method 
		
		
	请求结束:
		根据当前线程的唯一标记,将“字典”上的数据移除。

猜你喜欢

转载自blog.csdn.net/qq_27695659/article/details/88739733
今日推荐