<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          restful-djrestful 自動(dòng)路由框架

          聯(lián)合創(chuàng)作 · 2023-09-19 07:13

          restful-dj 是一個(gè)基于 Django2/3 的 restful 自動(dòng)路由框架。

          此包解決的問題:

          • 告別 Django 繁鎖的路由配置
          • 更便捷的 restful 編碼體驗(yàn)
          • 自動(dòng)解析/校驗(yàn)請(qǐng)求參數(shù),填充到路由處理函數(shù)

          安裝

          Gitee: https://gitee.com/hyjiacan/restful-dj Github: https://github.com/hyjiacan/restful-dj PyPI: https://pypi.org/project/restful-dj/

          pip install restful-dj

          使用

          此組件提供的包(package)名稱為 restful_dj,所有用到的模塊都在此包下引入。

          注冊(cè)

          在項(xiàng)目的根 urls.py 文件中,使用以下配置

          from django.urls import path
          import restful_dj
          
          urlpatterns = [
              path('any/prefix', restful_dj.urls)
          ]

          其中,any/prefix 是用戶自定義的url前綴,可以使用空串 ''

          注:可以通過部署地址 any/prefix 訪問接口列表 (僅在開發(fā)模式時(shí)可用)。

          配置

          配置項(xiàng)需要寫到 settings.py 文件中。

          RESTFUL_DJ = {
              'global_class': ['path.to.CustomClass',],
              'routes': {
                  'path.prefix': 'path.to',
              },
              'middleware': [
                  'path.to.MiddlewareClass'
              ],
              'logger': 'path.to.logger'
          }
          • global_class 當(dāng)在路由裝飾器參數(shù)中使用了自定義的值類型時(shí)(比如枚舉或類),應(yīng)該當(dāng)將其添加到此處,否則無法正確收集到路由
          • routes 路由映射配置,即將指定的請(qǐng)求路徑映射到指定的代碼路徑(路徑應(yīng)為基于項(xiàng)目根目錄的相對(duì)路徑)
          • middleware 中間件配置,其值為一個(gè) list,第一個(gè)填寫一個(gè)中間件的完整限定名稱
          • logger 默認(rèn)的日志是直接打印到控制臺(tái)的,可以通過設(shè)置此值以實(shí)現(xiàn)重定向日志輸出

          test.py

          from restful_dj import route
          from enums import RouteTypes
          @route('module_name', 'route_name', route_type = RouteTypes.TEST)
          def test(req):
              pass

          enums.py

          from enum import Enum
          class RouteTypes(Enum):
              TEST = 1

          編寫路由

          路由文件位置沒有要求,只要配置好就可以了。

          test/api/demo.py

          from django.http import HttpRequest
          from restful_dj.decorator import route
          
          @route(module='module-name', name='name')
          def get(request, param1, param2=None, param3: int =5):
              # request 會(huì)是 HttpRequest
              return {
                  'param1': param1, 
                  'param2': param2, 
                  'param3': param3, 
              }
          
          @route(module='module-name', name='name')
          def get_param(param1, req: HttpRequest, from_=None, param3 =5):
              # req 會(huì)是 HttpRequest
              return {
                  'param1': param1, 
                  'from': from_, 
                  'param3': param3,
              } 
          
          @route(module='module-name', name='name')
          def get_param(request: str, param1, from_=None, param3 =5):
              # request 會(huì)是請(qǐng)求參數(shù),參數(shù)列表中沒有 HttpRequest
              return {
                  'request': request,
                  'param1': param1, 
                  'from': from_, 
                  'param3': param3,
              } 
          
          @route(module='module-name', name='name')
          def get_param(request, param1, from_=None, param3 =5, **kwargs):
              # 未在函數(shù)的參數(shù)列表中聲明的請(qǐng)求參數(shù),會(huì)出現(xiàn)在 kwargs 中
              return {
                  'param1': param1,
                  'from': from_,
                  'param3': param3,
                  'variable_args': kwargs
              }
          

          一些需要注意的地方:

          • 當(dāng)代碼中需要使用關(guān)鍵字作為名稱時(shí),請(qǐng)?jiān)诿Q后添加 _,此時(shí)前端請(qǐng)求時(shí),_ 符號(hào)可省略, 如: from_ 在請(qǐng)求時(shí)可寫作 from=test (from_=test 亦可)。
          • 對(duì)于語言間的命令差異,可以自動(dòng)兼容 下劃線命名法 與 駝峰命名法,如:請(qǐng)求參數(shù)中的 pageIndex,在處理函數(shù)中可以寫作 page_index_page_index_ , 也就是說,在前后添加 _ 符號(hào)都不會(huì)影響參數(shù)的解析。
          • 路由處理函數(shù)可以添加一個(gè)可變參數(shù)(如:**kwargs**),用于接收未在參數(shù)列表中列出的請(qǐng)求項(xiàng)。 當(dāng)然,kwargs和普通函數(shù)一樣,可以是任何其它名稱。
          • request 參數(shù)(與參數(shù)位置無關(guān)),可能被解析成三種結(jié)果(12均會(huì)將其作為 HttpRequest 參數(shù)處理):
            1. 參數(shù)名稱為 request,并且未指定參數(shù)類型(或指定類型為 HttpRequest)
            2. 參數(shù)類型為 HttpRequest,參數(shù)名稱可以是任何合法的標(biāo)識(shí)符
            3. 參數(shù)名稱為 request,聲明了不是 HttpRequest 的類型,此時(shí)會(huì)被解析成一般的請(qǐng)求參數(shù)

          再寫配置

          RESTFUL_DJ = {
              'routes': {
                  'test': 'test.api',
              }
          }

          此配置表示,所有請(qǐng)求中以 test 開頭的地址,都會(huì)交由 test.api 下的模塊進(jìn)行處理。

          前端調(diào)用:

          // 請(qǐng)求 get 函數(shù)
          ajax.get('test.demo?param1=1&param2=2&param3=3')
          
          // 請(qǐng)求 get_param 函數(shù)
          ajax.get('test.demo/param?param1=1&param2=2&param3=3')

          路由可以返回任何類型的數(shù)據(jù)。路由會(huì)自動(dòng)根據(jù)函數(shù)定義來判斷傳入?yún)?shù)的類型是否合法。

          比如前面示例中的 param3: int =5,會(huì)根據(jù)聲明類型 int 去判斷傳入類型

          • 如果傳入了字符串類型的數(shù)值,路由會(huì)自動(dòng)轉(zhuǎn)換成數(shù)值類型
          • 另外,如果設(shè)置了 None 以外的默認(rèn)值,那么路由會(huì)根據(jù)默認(rèn)值的類型自動(dòng)去判斷, 此時(shí)可以省略參數(shù)類型,如: param3: int =5 省略為 param3=5

          裝飾器 route

          裝飾器 route 用于聲明某個(gè)函數(shù)可以被路由使用。通過添加此裝飾器以限制非路由函數(shù)被非法訪問。

          聲明為:

          def route(module=None, name=None, permission=True, ajax=True, referer=None, **kwargs):
              pass
          • module 此路由所屬的業(yè)務(wù)/功能模塊名稱
          • name 此路由的名稱
          • permission 設(shè)置此路由是否有權(quán)限控制
          • ajax 設(shè)置此路由是否僅允許 ajax 訪問 保留參數(shù)
          • referer 設(shè)置此路由允許的 referer 地址 保留參數(shù)
          • **kwargs 額外參數(shù)

          這些參數(shù)都會(huì)被傳遞給中間件的各個(gè)函數(shù)的參數(shù) meta。詳細(xì)見 RouteMeta

          同時(shí),此裝飾器會(huì)自動(dòng)嘗試將 request.body 處理成 JSON 格式(僅在 content-type=application/json 時(shí)),并且添加到 request.B 屬性上。

          另外,此裝飾器會(huì)自動(dòng)將 request.GET 和 request.POST 處理成為可以通過點(diǎn)號(hào)直接訪問的對(duì)象,分別添加到 request.G 和 request.P 上。例:

          # 原始數(shù)據(jù)
          request = {...}
          request.GET = {
              'param1': 1,
              'param2': 2
          }
          # 此時(shí),只能這樣訪問
          request.GET['param1']
          
          # 而在經(jīng)過裝飾器的處理后,可以這樣訪問
          request.G.param1

          但是,一般情況下,使用路由處理函數(shù)就能完全操作請(qǐng)求參數(shù)的, 所以需要在代碼中盡量減少使用 B/P/G,以避免代碼的不明確性。

          分發(fā)前的處理 (可選)

          有的時(shí)候,需要在分發(fā)前對(duì)請(qǐng)求參數(shù)進(jìn)行處理。此時(shí)可以使用 restful.set_before_dispatch_handler 來進(jìn)行一些預(yù)處理。

          函數(shù)簽名:

          def set_before_dispatch_handler(handler):
              pass

          用法:

          import restful_dj
          
          def before_dispatch_handler(request, entry, name):
              # 可以在此處修改 request 的數(shù)據(jù)
              # 也可以重新定義 entry 和 name
              return entry, name
          
          restful_dj.set_before_dispatch_handler(before_dispatch_handler)

          編寫中間件 (可選)

          RouteMeta

          路由元數(shù)據(jù)。

          from types import FunctionType
          from typing import OrderedDict
          
          class RouteMeta:  
              @property
              def handler(self) -> FunctionType:
                  """
                  路由處理函數(shù)對(duì)象
                  :return:
                  """
                  return self._handler
          
              @property
              def func_args(self) -> OrderedDict:
                  """
                  路由處理函數(shù)參數(shù)列表
                  :return:
                  """
                  return self._func_args
          
              @property
              def id(self) -> str:
                  """
                  路由ID,此ID由路由相關(guān)信息組合而成
                  :return:
                  """
                  return self._id
          
              @property
              def module(self) -> str:
                  """
                  裝飾器上指定的 module 值
                  :return:
                  """
                  return self._module
          
              @property
              def name(self) -> str:
                  """
                  裝飾器上指定的 name 值
                  :return:
                  """
                  return self._name
          
              @property
              def permission(self) -> bool:
                  """
                  裝飾器上指定的 permission 值
                  :return:
                  """
                  return self._permission
          
              @property
              def ajax(self) -> bool:
                  """
                  裝飾器上指定的 ajax 值
                  :return:
                  """
                  return self._ajax
          
              @property
              def referer(self) -> str:
                  """
                  裝飾器上指定的 referer 值
                  :return:
                  """
                  return self._referer
          
              @property
              def kwargs(self) -> dict:
                  """
                  裝飾器上指定的其它參數(shù)
                  :return:
                  :rtype: Dict
                  """
                  return self._kwargs

          注冊(cè)到 settings.py 的 RESTFUL_DJ.middleware 列表中。中間件將按順序執(zhí)行。

          需要注意: 每一個(gè)中間件在程序運(yùn)行期間共享一個(gè)實(shí)例。

          path.to.MiddlewareClass

          from django.http import HttpRequest
          from restful_dj import RouteMeta 
          
          class MiddlewareClass:
              """
              路由中間件
              """
          
              def process_request(self, request: HttpRequest, meta: RouteMeta, **kwargs):
                  """
                  對(duì) request 對(duì)象進(jìn)行預(yù)處理。一般用于請(qǐng)求的數(shù)據(jù)的解碼,此時(shí)路由組件尚水進(jìn)行請(qǐng)求數(shù)據(jù)的解析(B,P,G 尚不可用)
                  :param request:
                  :param meta:
                  :return: 返回 HttpResponse 以終止請(qǐng)求,返回 False 以停止執(zhí)行后續(xù)的中間件(表示訪問未授權(quán)),返回 None 或不返回任何值繼續(xù)執(zhí)行后續(xù)中間件
                  """
                  pass
          
              def process_invoke(self, request: HttpRequest, meta: RouteMeta, **kwargs):
                  """
                  在路由函數(shù)調(diào)用前,對(duì)其參數(shù)等進(jìn)行處理,此時(shí)路由組件已經(jīng)完成了請(qǐng)求數(shù)據(jù)的解析(B,P,G 已可用)
                  此時(shí)可以對(duì)解析后的參數(shù)進(jìn)行變更
                  :param request:
                  :param meta:
                  :return: 返回 HttpResponse 以終止請(qǐng)求,返回 False 以停止執(zhí)行后續(xù)的中間件(表示訪問未授權(quán)),返回 None 或不返回任何值繼續(xù)執(zhí)行后續(xù)中間件
                  """
                  pass
          
              def process_return(self, request: HttpRequest, meta: RouteMeta, **kwargs):
                  """
                  在路由函數(shù)調(diào)用后,對(duì)其返回值進(jìn)行處理
                  :param request:
                  :param meta:
                  :param kwargs: 始終會(huì)有一個(gè) 'data' 的項(xiàng),表示返回的原始數(shù)據(jù)
                  :return: 返回 HttpResponse 以終止執(zhí)行,否則返回新的 return value
                  """
                  assert 'data' in kwargs
                  return kwargs['data']
          
              def process_response(self, request: HttpRequest, meta: RouteMeta, **kwargs):
                  """
                  對(duì) response 數(shù)據(jù)進(jìn)行預(yù)處理。一般用于響應(yīng)的數(shù)據(jù)的編碼
                  :rtype: HttpResponse
                  :param meta:
                  :param request:
                  :param kwargs: 始終會(huì)有一個(gè) 'response' 的項(xiàng),表示返回的 HttpResponse
                  :return: 無論何種情況,應(yīng)該始終返回一個(gè)  HttpResponse
                  """
                  assert 'response' in kwargs
                  return kwargs['response']

          設(shè)置日志記錄器 (可選)

          from restful_dj import set_logger
          
          def my_logger(level: str, message: str, e: Exception):
              pass
          
          set_logger(my_logger)

          其中,level表示日志級(jí)別,會(huì)有以下值:

          • debug
          • info
          • success
          • warning
          • error

          路由收集

          路由收集器用于收集項(xiàng)目中的所有路由,通過以下方式調(diào)用:

          from restful_dj import collector
          routes = collector.collect()

          routes 是一個(gè)可以直接迭代的路由數(shù)組

          在發(fā)布產(chǎn)品到線上時(shí),通過此方法將自動(dòng)產(chǎn)生 Django 的路由配置文件,以提高線上性能。

          瀏覽 22
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          編輯 分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          編輯 分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  日韩欧美动作影片 | 日日三级网 | 一级片黄色视频 | 国产日韩欧美操 | 日韩3级|