在djangorestframework中使用yaml格式的注釋生成swagger文檔

0x01

最近在項目中要對api進行大規(guī)模重構(gòu)礁凡,并且工具源碼注釋生成文檔响禽,比較swagger和spihx之后骏全,覺得swagger更適合做api文檔,可以在web頁面中直接請求對應(yīng)的api画切,很是方便。使用最新版的django-rest-swagger(drs)生成djangorestframework(drf)生成文檔的時候囱怕,drs只會根據(jù)視圖中的docstring來生成Link(swagger的單條文檔記錄)的描述霍弹,根據(jù)ViewSet中的serializer中定義的fields以及pagination_class定義的分頁類來生成parameters,如果想要根據(jù)文檔來插入一些parameters時娃弓,可以發(fā)現(xiàn)drs的可定制化程度很低典格,于是我決定做一些定制化。

0x02 代碼

在制定花的過程中我主要重寫了drf中的SchemaGenerator的get_description台丛,把視圖中的docstring按照yaml格式解析出來耍缴,并且返回docstring中的第一行作為description,如果視圖沒有docstring的話齐佳,_SchemaGenerator會按照視圖名稱自動生成相應(yīng)的description私恬。接下來是重寫get_link方法,前面說過炼吴,一條Link是swagger頁面中的一條文檔記錄本鸣,如果有yamlobj的話,則根據(jù)固定的格式解析yamlobj硅蹦,然后解析出來的屬性加到Link當中去荣德。最后重寫get_swagger_view 方法,使用新寫的SchemaGenerator童芹。

from rest_framework.schemas import SchemaGenerator as _SchemaGenerator
from rest_framework_swagger import renderers
from rest_framework.compat import coreapi, urlparse
from django.utils.encoding import smart_text
from rest_framework.utils import formatting

class SchemaGenerator(_SchemaGenerator):
    def get_description(self, path, method, view):
        method_name = getattr(view, 'action', method.lower())
        method_docstring = getattr(view, method_name, None).__doc__
        self.yamlobj = None
        if method_docstring:
            method_docstring = formatting.dedent(smart_text(method_docstring))
            self.yamlobj = yaml.load(method_docstring)
            return method_docstring.splitlines()[0]
        return super(SchemaGenerator, self).get_description(path, method, view)

    def get_link(self, path, method, view):
        """
        Return a `coreapi.Link` instance for the given endpoint.
        """
        fields = self.get_path_fields(path, method, view)
        fields += self.get_serializer_fields(path, method, view)
        fields += self.get_pagination_fields(path, method, view)
        fields += self.get_filter_fields(path, method, view)

            if fields and any([field.location in ('form', 'body') for field in fields]):
                encoding = self.get_encoding(path, method, view)
            else:
                encoding = None

            description = self.get_description(path, method, view)
            if isinstance(self.yamlobj, dict):
                def get_localtion(parameter):
                    if method == 'GET':
                        return 'query'
                    return parameter.get('paramType', 'formData')
                parameters = self.yamlobj.get('parameters', [])
                fields += [coreapi.Field(name=x['name'], location=get_localtion(x),     required=x.get('required', True, ), description=x.get('description', ''),     type=x.get('type', 'string')) for x in parameters]

            if self.url and path.startswith('/'):
                path = path[1:]

            return coreapi.Link(
                url=urlparse.urljoin(self.url, path),
                action=method.lower(),
                encoding=encoding,
                fields=fields,
                description=description
        )


def get_swagger_view(title=None, url=None, patterns=None, urlconf=None):
    """
    Returns schema view which renders Swagger/OpenAPI.
    """
    class SwaggerSchemaView(APIView):
        _ignore_model_permissions = True
        exclude_from_schema = True
        permission_classes = [AllowAny]
        renderer_classes = [
            CoreJSONRenderer,
            renderers.OpenAPIRenderer,
            renderers.SwaggerUIRenderer
        ]

        def get(self, request):
            generator = SchemaGenerator(
                title=title,
                url=url,
                patterns=patterns,
                urlconf=urlconf
            )
             schema = generator.get_schema(request=request)

            if not schema:
                raise exceptions.ValidationError(
                    'The schema generator did not return a schema Document'
                )

            return Response(schema)

    return SwaggerSchemaView.as_view()
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末涮瞻,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子假褪,更是在濱河造成了極大的恐慌署咽,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,843評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件生音,死亡現(xiàn)場離奇詭異宁否,居然都是意外死亡,警方通過查閱死者的電腦和手機缀遍,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,538評論 3 392
  • 文/潘曉璐 我一進店門慕匠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人域醇,你說我怎么就攤上這事台谊∪叵保” “怎么了?”我有些...
    開封第一講書人閱讀 163,187評論 0 353
  • 文/不壞的土叔 我叫張陵锅铅,是天一觀的道長酪呻。 經(jīng)常有香客問我,道長狠角,這世上最難降的妖魔是什么号杠? 我笑而不...
    開封第一講書人閱讀 58,264評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮丰歌,結(jié)果婚禮上姨蟋,老公的妹妹穿的比我還像新娘。我一直安慰自己立帖,他們只是感情好眼溶,可當我...
    茶點故事閱讀 67,289評論 6 390
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著晓勇,像睡著了一般堂飞。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上绑咱,一...
    開封第一講書人閱讀 51,231評論 1 299
  • 那天绰筛,我揣著相機與錄音,去河邊找鬼描融。 笑死铝噩,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的窿克。 我是一名探鬼主播骏庸,決...
    沈念sama閱讀 40,116評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼年叮!你這毒婦竟也來了具被?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,945評論 0 275
  • 序言:老撾萬榮一對情侶失蹤只损,失蹤者是張志新(化名)和其女友劉穎一姿,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體跃惫,經(jīng)...
    沈念sama閱讀 45,367評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡叮叹,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,581評論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了辈挂。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,754評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡裹粤,死狀恐怖终蒂,靈堂內(nèi)的尸體忽然破棺而出蜂林,到底是詐尸還是另有隱情,我是刑警寧澤拇泣,帶...
    沈念sama閱讀 35,458評論 5 344
  • 正文 年R本政府宣布噪叙,位于F島的核電站,受9級特大地震影響霉翔,放射性物質(zhì)發(fā)生泄漏睁蕾。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,068評論 3 327
  • 文/蒙蒙 一债朵、第九天 我趴在偏房一處隱蔽的房頂上張望子眶。 院中可真熱鬧,春花似錦序芦、人聲如沸臭杰。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,692評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽渴杆。三九已至,卻和暖如春宪塔,著一層夾襖步出監(jiān)牢的瞬間磁奖,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,842評論 1 269
  • 我被黑心中介騙來泰國打工某筐, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留比搭,地道東北人。 一個月前我還...
    沈念sama閱讀 47,797評論 2 369
  • 正文 我出身青樓来吩,卻偏偏與公主長得像敢辩,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子弟疆,可洞房花燭夜當晚...
    茶點故事閱讀 44,654評論 2 354

推薦閱讀更多精彩內(nèi)容