当前位置:网站首页>tornado项目之路由装饰器
tornado项目之路由装饰器
2022-07-04 07:05:00 【youhebuke225】
- 当我们进行启动项目的时候,首先需要的就是注册路由,所以我们可以定义一个方法,这个方法叫
get_handlers,来获取整个项目的路由 - 但是如何表示一个类是一个路由呢?这个时候,我们就用到了装饰器
open_handler,经过这个装饰器装饰的类,那么他就是一个路由,所以open_handler至少有两个参数path路径index用于路由排序
装饰器
我们在目录tornado项目core\decorators\open_handler下写一个装饰器,类作为装饰器 点击
class HandlerDecorate:
"""路由装饰器 1. 实质上路由装饰器只是给装饰的类添加了__url_path__的属性 2. 我们初始化的时候就通过__url_path__这个属性来判断当前的类是路由的处理器 3. __url_path_index__用来给路由进行排序 """
def __init__(self, path, index=None) -> None:
self.__url_path__ = path
self.__url_path_index__ = index
def __call__(self, cls):
cls.__url_path__ = self.__url_path__
cls.__url_path_index__ = self.__url_path_index__
return cls
我们在__init__.py中暴露这个装饰器
from core.decorators.open_handler.index import HandlerDecorate
open_handler = HandlerDecorate
只要经过@open_hander修饰的类,就会含有__url_paht__属性,如
@open_handler(path="/api/(.*)", index=1)
class openApiHandlerService(RequestHandler):
def get(self, *args, **kwargs):
self.write("hello world")
self.finish()
那么,openApiHandlerService就会含有__url_paht__属性为/api/(.*)
路由的收集
定义get_handlers方法,来获取被装饰器修饰的类
遍历项目文件
我们需要定义一个遍历项目文件的函数,当前函数用于查找项目中被
open_handler修饰的类
我们在core\utils\module_utils.py下,新建一个函数,用于遍历得到某文件下的所有的module
import importlib
import pkgutil
import os
def get_all_modules(path, file_name):
""" 获取路径下的所有file_name的module """
# 获取目录的配置(目录必须是一个包,才会有__path__属性)
_app = importlib.import_module(path)
def get_all_moudules_name(package_path, prefix=""):
# 用于深度遍历文件夹
for loader, name, is_package in pkgutil.iter_modules([package_path]):
if is_package:
# 如果还是一个包,那么再次遍历,且遍历的时候加上前缀
for _name in get_all_moudules_name(os.path.join(package_path, name), prefix=f"{
name}."):
yield prefix + _name
else:
yield prefix + name
return [
importlib.import_module(f"{
path}.{
module_name}")
for module_name in get_all_moudules_name(_app.__path__[0])
if module_name.split(".")[-1][:len(file_name)] == file_name
]
为了规范,我们所有的路由定义的类都凡在开都为handlers的文件中
获取项目下所有的路由
我们在core\decorators\open_handler下新建一个OpenHandler的类,并定义一个get_handlers的方法用来获取所有的路由
class OpenHandler:
"""路由容器 1. 初始化的时候获取路由的容器类和工具类 2. 返回tornado路由列表 """
def __init__(self, source_libs) -> None:
self.source_libs = source_libs # 传递目录名,用于获取目录下所有使用装饰器的类
self.handler_libs = [] # 存储路由的容器
def get_handlers(self):
self._handler_libs_ = []
_modules = [] # 目录下所有的moudule容器
for _path in self.source_libs:
_modules += get_all_modules(_path, "handler")
for _module in _modules:
self.handler_libs += [
dict(
path=_member.__url_path__,
handler=f"{
_member.__module__}.{
_member.__name__}",
index = _member.__url_path_index__
)
for _name,_member in inspect.getmembers(_module, inspect.isclass)
if hasattr(_member, "__url_path__")
]
# 排序
self.handler_libs.sort(key=lambda x: x['index'])
# 生成tornado的路由对象
_result = []
for _handler_lib in self.handler_libs:
# 遍历生成tornado的路由对象
_path = _handler_lib.get("path")
_result.append(
url(_path, import_object(_handler_lib.get("handler"))))
# 所有的路由列表
return _result
注册路由
一般我们在启动项目的时候需要注册路由
获取handler下的所有路由
为了项目规范我们把所有的路由都注册在了命名为
handler的文件夹下,在启动环境的时候,我们一般调用Environment类下的方法,我们在Environment下,写一个获取handler下的路由的方法
class Environment:
...
def get_all_handlers(self):
open_handler = OpenHandler(["core"])
return open_handler.get_handlers()
他所表示的是获取core文件夹下的所有的路由,然后我们进行路由的注册
class Application(Application):
def __init__(self):
# 初始化数据库、redis等,项目启动的时候,不要引入模型类
# 注册路由
handlers = environment.get_all_handlers()
# 添加动态路由
super().__init__(handlers, **config.settings)
测试
- 启动项目,我们输入
http://localhost:8888/api/,就会发现我们可以访问到注册的路由了 
边栏推荐
- Mysql 45讲学习笔记(六)全局锁
- NLP literature reading summary
- 关于IDEA如何设置快捷键集
- notepad++如何统计单词数量
- Node connection MySQL access denied for user 'root' @ 'localhost' (using password: yes
- tars源码分析之8
- Selenium driver ie common problem solving message: currently focused window has been closed
- Summary of MySQL common judgment functions!! Have you used it
- Selection (023) - what are the three stages of event propagation?
- Enter the year, month, and determine the number of days
猜你喜欢

"Sword finger offer" 2nd Edition - force button brush question

Master-slave replication principle of MySQL database

About how idea sets up shortcut key sets

Pangu open source: multi support and promotion, the wave of chip industry

Boosting the Performance of Video Compression Artifact Reduction with Reference Frame Proposals and
![[GF (q) + LDPC] regular LDPC coding and decoding design and MATLAB simulation based on the GF (q) field of binary graph](/img/5e/7ce21dd544aacf23b4ceef1ec547fd.png)
[GF (q) + LDPC] regular LDPC coding and decoding design and MATLAB simulation based on the GF (q) field of binary graph

Selenium ide plug-in download, installation and use tutorial

响应式——媒体查询

用于压缩视频感知增强的多目标网络自适应时空融合

两年前美国芯片扭捏着不卖芯片,如今芯片堆积如山祈求中国帮忙
随机推荐
[Mori city] random talk on GIS data (I)
【GF(q)+LDPC】基于二值图GF(q)域的规则LDPC编译码设计与matlab仿真
tars源码分析之3
tars源码分析之8
响应式——媒体查询
Boast about Devops
Introduction to spark core components
MySQL storage engine
期末周,我裂开
Code rant: from hard coding to configurable, rule engine, low code DSL complexity clock
2022 is probably the best year for the economy in the next 10 years. Did you graduate in 2022? What is the plan after graduation?
About how idea sets up shortcut key sets
MySQL 45 lecture learning notes (VII) line lock
在已經知道錶格列勾選一個顯示一列
BasicVSR++: Improving Video Super-Resolutionwith Enhanced Propagation and Alignment
测试用例的设计
What is industrial computer encryption and how to do it
NLP literature reading summary
Enter the year, month, and determine the number of days
tcp socket 的 recv 如何接收指定长度消息?