欧美一区二区三区老妇人-欧美做爰猛烈大尺度电-99久久夜色精品国产亚洲a-亚洲福利视频一区二区

PythonWeb開發(fā):教你如何解放路由管理

1. 痛點(diǎn)

隨著業(yè)務(wù)的飛速發(fā)展,API接口越來越多,路由管理文件從幾十號(hào)變成幾百上千行,且每次上新服務(wù),需要在修改路由文件代碼,帶來一定的風(fēng)險(xiǎn)。

成都創(chuàng)新互聯(lián)是一家專注于成都做網(wǎng)站、網(wǎng)站制作與策劃設(shè)計(jì),袁州網(wǎng)站建設(shè)哪家好?成都創(chuàng)新互聯(lián)做網(wǎng)站,專注于網(wǎng)站建設(shè)十載,網(wǎng)設(shè)計(jì)領(lǐng)域的專業(yè)建站公司;建站業(yè)務(wù)涵蓋:袁州等地區(qū)。袁州做網(wǎng)站價(jià)格咨詢:13518219792

Python Web開發(fā): 教你如何解放路由管理

2. 解決方案

  • 既然路由文件隨著業(yè)務(wù)的擴(kuò)展越來越龐大,那就去掉路由文件。
  • 制定對(duì)應(yīng)規(guī)則,路由通過API文件名根據(jù)一定的規(guī)則對(duì)應(yīng)類名,然后自動(dòng)導(dǎo)入對(duì)應(yīng)實(shí)現(xiàn)類,注冊(cè)到Web框架中。

    2.1 制定規(guī)則

    下面這套規(guī)則只是其中一種方案,可以針對(duì)項(xiàng)目情況制定對(duì)應(yīng)的規(guī)則,然后實(shí)現(xiàn)相關(guān)代碼,但是整體思路基本一樣。

    1. 代碼目錄結(jié)構(gòu),列一下簡(jiǎn)單的項(xiàng)目文件目錄,下面以flask框架為例:
      Python Web開發(fā): 教你如何解放路由管理
      app.py是啟動(dòng)文件。
      resources是API接口代碼文件夾。
      services是為API接口服務(wù)的函數(shù)封裝文件夾。
      如果項(xiàng)目還有依賴文件,也可以單獨(dú)再建其他文件夾。

    2. 項(xiàng)目的API接口代碼均放在resources文件夾下,且此文件夾只能寫接口API服務(wù)代碼。

    3. 接口名稱命名以_連接單詞,而對(duì)應(yīng)文件里的類名文件名稱的單詞,不過換成是駝峰寫法。

    4. 類的導(dǎo)入則通過文件名對(duì)應(yīng)到類名,實(shí)現(xiàn)自動(dòng)映射注冊(cè)到web框架中。

    規(guī)則舉例如下:
    如上圖,resources下有一個(gè)hello_world接口,還有一個(gè)ab項(xiàng)目文件夾,ab下面還有一個(gè)hello_world_python接口以及子項(xiàng)目文件夾testab, testab下面也有一個(gè)hello_world_python.

    • 接口文件的文件名命名規(guī)范:
      文件名命名均為小寫,多個(gè)單詞之間使用'_'隔開,比如hello_world.py 命名正確,helloWorld.py命名錯(cuò)誤。

    • 接口文件里的接口類Class命名是以文件名字轉(zhuǎn)為駝峰格式,且首字母大寫。比如hello_world.py 對(duì)應(yīng)的接口類是 HelloWorld
      舉例: hello_world.py
      Python Web開發(fā): 教你如何解放路由管理
      hello_world_python.py
      Python Web開發(fā): 教你如何解放路由管理
    1. 路由入口文件會(huì)自動(dòng)映射,映射規(guī)則為:
      前綴 / 項(xiàng)目文件夾[...] / 文件名

      其中 前綴為整個(gè)項(xiàng)目的路由前綴,可以定義,也可以不定義,比如api-ab項(xiàng)目,可以定義整個(gè)項(xiàng)目的路由前綴為 ab/
      resource下面項(xiàng)目文件夾如果有,則會(huì)自動(dòng)拼接,如果沒有,則不會(huì)讀取。
      舉例
      前綴為空,上圖resources中的三個(gè)接口對(duì)應(yīng)的路由為:

      hello_world.py ==>  /hello_world
      ab/hello_world_python.py ==> /ab/hello_world_python
      ab/testab/hello_world_python.py ==> /ab/testab/hello _world_python

      前綴為ab/,上圖resources中的三個(gè)接口對(duì)應(yīng)的路由為:

      hello_world.py ==> ab/hello_world
      ab/hello_world_python.py ==> ab/ab/hello_world_python
      ab/testab/hello_world_python.py ==> ab/ab/testab/hello_world_python
    2. 關(guān)于resources里目錄結(jié)構(gòu),代碼里是可以允許N層,但建議不要超過3層, 不易管理。

2.2 代碼實(shí)現(xiàn)

python很多框架的啟動(dòng)和路由管理都很類似,所以這套規(guī)則適合很多框架,測(cè)試過程中有包括flask, tornado, sanic, japronto。 以前年代久遠(yuǎn)的web.py也是支持的。

完整代碼地址:
https://github.com/CrystalSkyZ/PyAutoApiRoute

  1. 實(shí)現(xiàn)下劃線命名 轉(zhuǎn) 駝峰命名 函數(shù),代碼演示:

    def underline_to_hump(underline_str):
    '''
    下劃線形式字符串轉(zhuǎn)成駝峰形式,首字母大寫
    '''
    sub = re.sub(r'(_\w)', lambda x: x.group(1)[1].upper(), underline_str)
    if len(sub) > 1:
        return sub[0].upper() + sub[1:]
    return sub
  2. 實(shí)現(xiàn)根據(jù)字符串導(dǎo)入模塊函數(shù), 代碼演示:

    • 通過python內(nèi)置函數(shù)__import__函數(shù)實(shí)現(xiàn)加載類

          def import_object(name):
          """Imports an object by name.
          import_object('x') is equivalent to 'import x'.
          import_object('x.y.z') is equivalent to 'from x.y import z'.
          """
          if not isinstance(name, str):
                  name = name.encode('utf-8')
          if name.count('.') == 0:
                  return __import__(name, None, None)
      
          parts = name.split('.')
          obj = __import__('.'.join(parts[:-1]), None, None, [parts[-1]], 0)
          try:
                  return getattr(obj, parts[-1])
          except AttributeError:
                  raise ImportError("No module named %s" % parts[-1])
    • 通過importlib模塊實(shí)現(xiàn)
      importlib.import_module(name)

    上面2種方法都可以,github上代碼里2種方法都有測(cè)試。

  3. 檢索resources文件夾,生成路由映射,并導(dǎo)入對(duì)應(yīng)實(shí)現(xiàn)類, 代碼演示如下:

    def route(route_file_path,
          resources_name="resources",
          route_prefix="",
          existing_route=None):
    
    route_list = []
    
        def get_route_tuple(file_name, route_pre, resource_module_name):
            """
            :param file_name: API file name
            :param route_pre: route prefix
            :param resource_module_name: resource module
            """
            nonlocal route_list
            nonlocal existing_route
            route_endpoint = file_name.split(".py")[0]
            #module = importlib.import_module('{}.{}'.format(
            #    resource_module_name, route_endpoint))
            module = import_object('{}.{}'.format(
                resource_module_name, route_endpoint))
            route_class = underline_to_hump(route_endpoint)
            real_route_endpoint = r'/{}{}'.format(route_pre, route_endpoint)
            if existing_route and isinstance(existing_route, dict):
                if real_route_endpoint in existing_route:
                    real_route_endpoint = existing_route[real_route_endpoint]
            route_list.append((real_route_endpoint, getattr(module, route_class)))
    
        def check_file_right(file_name):
            if file_name.startswith("_"):
                return False
            if not file_name.endswith(".py"):
                return False
            if file_name.startswith("."):
                return False
            return True
    
        def recursive_find_route(route_path, sub_resource, route_pre=""):
            nonlocal route_prefix
            nonlocal resources_name
            file_list = os.listdir(route_path)
            if config.DEBUG:
                print("FileList:", file_list)
            for file_item in file_list:
                if file_item.startswith("_"):
                    continue
                if file_item.startswith("."):
                    continue
                if os.path.isdir(route_path + "/{}".format(file_item)):
                    recursive_find_route(route_path + "/{}".format(file_item), sub_resource + ".{}".format(file_item), "{}{}/".format(route_pre, file_item))
                    continue
                if not check_file_right(file_item):
                    continue
                get_route_tuple(file_item, route_prefix + route_pre, sub_resource)
    
    recursive_find_route(route_file_path, resources_name)
    if config.DEBUG:
        print("RouteList:", route_list)
    
    return route_list
    • get_route_tuple函數(shù)作用是通過字符串導(dǎo)入類,并將路由和類以元組的方式添加到數(shù)組中。
    • check_file_right函數(shù)作用是過濾文件夾中不合法的文件。
    • recursive_find_route函數(shù)采用遞歸查找resources中的文件。
    • existing_route參數(shù)是將已經(jīng)線上存在的路由替換新規(guī)則生成的路由,這樣舊項(xiàng)目也是可以優(yōu)化使用這套規(guī)則。

3. 應(yīng)用到項(xiàng)目中

以flask框架為例,其余框架請(qǐng)看github中的代碼演示。
app.py 中代碼

   app = Flask(__name__)
   api = Api(app)
   # APi route and processing functions
   exist_route = {"/flask/hello_world": "/hello_world"}
   route_path = "./resources"
   route_list = route(
       route_path,
       resources_name="resources",
       route_prefix="flask/",
       existing_route=exist_route)

   for item in route_list:
       api.add_resource(item[1], item[0])

   if __name__ == "__main__":
       app.run(host="0.0.0.0", port=int(parse_args.port), debug=config.DEBUG)

運(yùn)行app.py之后,路由打印如下:

   RouteList: [
  ('/hello_world', <class'resources.hello_world.HelloWorld'>),
  ('/flask/ab/testab/hello_world_python_test', \
            <class 'resources.ab.testab.hello_world_python_test.HelloWorldPythonTest'>), 
  ('/flask/ab/hello_world_python', <class 'resources.ab.hello_world_python.HelloWorldPython'>)
  ]

元組第一個(gè)元素則是路由,第二個(gè)元素是對(duì)應(yīng)的實(shí)現(xiàn)類。


總結(jié):
至此,通過制定一定規(guī)則,解放路由管理文件方案完成。 歡迎各位一起討論其余比較好的方案,更多方案討論可以關(guān)注微信公眾號(hào): 天澄的技術(shù)筆記 。
Python Web開發(fā): 教你如何解放路由管理

本文題目:PythonWeb開發(fā):教你如何解放路由管理
分享路徑:http://chinadenli.net/article8/jsigip.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供軟件開發(fā)、定制網(wǎng)站、靜態(tài)網(wǎng)站、動(dòng)態(tài)網(wǎng)站網(wǎng)站改版、小程序開發(fā)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

商城網(wǎng)站建設(shè)
日韩成人h视频在线观看| 欧美日本精品视频在线观看| 欧美精品久久一二三区| 亚洲一区二区精品久久av| 激情国产白嫩美女在线观看| 熟女中文字幕一区二区三区| 风韵人妻丰满熟妇老熟女av| 老司机精品线观看86| 亚洲精品欧美精品一区三区| 国产精品视频一级香蕉| 精品欧美日韩一区二区三区| 亚洲av熟女国产一区二区三区站| 亚洲综合日韩精品欧美综合区| 亚洲国产av国产av| 国产免费自拍黄片免费看| 国产美女网红精品演绎| 色哟哟精品一区二区三区| 亚洲一区二区亚洲日本| 深夜视频在线观看免费你懂| 日本女优一区二区三区免费| 日本免费熟女一区二区三区| 人妻露脸一区二区三区| 五月婷婷六月丁香狠狠| 三级理论午夜福利在线看| 国产成人精品一区在线观看| 中文字幕无线码一区欧美| 久久大香蕉精品在线观看| 欧美精品一区二区水蜜桃| 老熟妇2久久国内精品| 日本中文在线不卡视频| 日韩成人中文字幕在线一区 | 伊人久久五月天综合网| 日本午夜免费观看视频| 国产午夜福利片在线观看| 国产午夜福利一区二区| 日本免费一区二区三女| 中文字幕一区二区三区大片| 深夜福利欲求不满的人妻| 日本人妻丰满熟妇久久| 亚洲欧美日本成人在线| 十八禁日本一区二区三区|