django-apiview


Namedjango-apiview JSON
Version 1.0.32 PyPI version JSON
download
home_page
SummaryA set of django tools to help you create JSON service..
upload_time2023-09-13 07:13:49
maintainerZhao JunXin
docs_urlNone
authorZhao JunXin
requires_python
licenseMIT
keywords django-apiview
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # django-apiview

## 安装

```
pip install django-apiview
```

## 关于其它依赖包的说明

- `django-apiview`中的`@cache`功能依赖于`django-redis`包。但我们并未将`django-redis`当成我们的依赖包,因为很多应用可能不会使用`@cache`功能。如果你需要使用`@cache`功能,则你需要将`django-redis`作为你的项目的依赖包。
- `django_apiview.clients.ApiviewClient`使用到了`requests`包,同理,我们也没有将其当成我们的依赖包。如果你需要使用`django_apiview.clients.ApiviewClient`,你也需要将`requests`作为你的项目的依赖包。

## 使用

```
from django_apiview.views import apiview

@apiview
def ping():
    """总是返回"pong"字符串常量。

    --------
    @methods: get
    @response: 200 OK "正确的响应" {{{
        "pong"
    }}}
    @response: 200 ERROR "错误的响应" {{{
        {
            "code": 1234,
            "message": "错误原因。"
        }
    }}}
    """
    return "pong"


@apiview
@string_length_limit("msg", max_length=4096, min_length=2)
def echo(msg: str):
    """总是返回你输入的内容。

    要求参数msg的长度范围为:[2, 4096]。

    --------
    @methods: post
    @parameter: body {{{
        in: body
        required: true
        example:
          msg: "测试的字符串"
    }}}
    @response: 200 OK "正确的响应" {{{
        "测试的字符串"
    }}}
    @response: 500 ERROR "错误的响应" {{{
        {
            "code": 1234,
            "message": "错误原因。"
        }
    }}}
    """
    return msg
```

1. 使用django-apiview定义接口,总是要加上@apiview注解,并且要求是第一个注解。
1. 可以使用多个辅助注解来进行参数检查和其他各类检查。
1. 接口函数只要返回业务层数据即可,django-apiview会对其进行序列化和业务协议封装。
1. 支持swagger接口管理界面自动生成。所有需要在swagger接口管理界面中显示的接口,需要在其docstring中添加swagger配置。

## 辅助注解

- django_apiview.helpers.auth
    - check_aclkey: 检查请求头/请求参数/请求数据中是否有aclkey字段,并且aclkey字段是否有效。
- django_apiview.helpers.cache
    - cache: 接口缓存支持。支持模型数据变动联动缓存清理。
- django_apiview.helpers.cipher
    - rsa_decrypt: 密码字段rsa加解密。
    - decode_encrypted_data: 业务数据整体rsa加解密。
- django_apiview.helpers.request_methods(如果不添加任何请求方式控制,则根据全局设置允许全部)
    - allow_get: 允许get请求方式。
    - allow_post: 允许post请求方式。
    - allow_put: 允许put请求方式。
    - allow_delete: 允许delete请求方式。
    - allow_patch: 允许patch请求方式。
    - allow_head: 允许head请求方式。
    - allow_options: 允许options请求方式。
- django_apiview.helpers.transformer
    - body_alias: 将body整体赋给新的变量
    - cookie_variable: 将cookie值赋给新的变量
    - meta_variable: 将meta值赋给新的变量
- django_apiview.helpers.validators
    - requires: 设置必填参数。
    - choices: 设置参数选项范围。
    - between: 设置参数取值范围。
    - string_length_limit: 设置参数长度范围。

## Swagger集成

### Swagger集成效果图

![django_apiview swagger集成效果](https://github.com/zencore-dobetter/pypi-images/raw/main/django-apiview/swagger.png)

### Swagger集成

*pro/settings.py*
```
INSTALLED_APPS = [
    ...
    "django_static_swagger_ui",
    "django_apiview",
    ...
]
```

*pro/urls.py*

```
from django.urls import path
from django.urls import include

urlpatterns = [
    ...
    path('apiview/', include("django_apiview.urls")),
    ...
]
```

- 配置如上。访问:http://127.0.0.1:8000/apiview/swagger-ui.html。
- 如何控制swagger的输出范围以及如何配置接口的swagger输出详见下面说明。

### Swagger Docstring规则

#### parameter规则

```
@parameter: <parameter_name> {{{
    <parameter_attributes>
}}}
```

- parameter_name: 字符串,变量名。
- parameter_attributes: json或yaml格式。遵循swagger-ui的参数语法。部分参数字段如下:
    - `in: [body, path, query, formData]` 表示参数来源
    - `required: true/false` 表示字段是否必填
    - `example:` 表示参数示例
    - `schema:`
        - `$ref: #/components/schemas/ModelName` 表示参数模型
    - `type: integer/string` 表示参数类型
- `@parameter:`,可以多次使用,显示多个参数。各参数的in属性可以不同,表示参数可以有不同的来源。
- `in: body`,较为特殊,一般只有一个,表示以json payload形式提交的数据整体。

使用举例:

```
@parameter: body {{{
    in: body
    required: true
    example:
        msg: "Example Message"
}}}
```

- `in: body`,表示参数使用json payload形式提交。
- `required: true`,表示参数是必填的。
- `example:\n    msg: "Example Message"`,表示参数示例,将显示在swagger的参数输入框中。

#### response规则

```
@response: <http_status_code> <respones_status> <respones_description> {{{
    <response_body>
}}}
```

- `http_status_code`,表示http响应状态码。一般为200,404,500等。除非系统级错误,正确响应和一般业务逻辑错误推荐使用200。
- `respones_status`,取值为OK或ERROR,表示业务状态。OK表示业务处理正确。ERROR表示业务处理异常。
- `respones_description`,表示本响应示例的业务说明。
- `response_body`,表示示例的响应体。只需要显示有效的业务数据部分即可。django-apiview或自动进行业务数据的封装,最终显示为完整的响应数据包。
- `@response`,可以多次使用,可以用来表示在不同情况下的响应。

使用举例:

```
@response: 200 OK "正确的响应" {{{
    "测试的字符串"
}}}
```

- `200`,表示http状态码为正确的http响应。
- `OK`,表示业务逻辑处理正确完成。
- `正确的响应`,表示以下的响应未例为正常情况下的响应数据。
- `测试的字符串`,表示返回的有效业务数据内容。如果使用SimpleJsonResultPacker业务封装协议,则最终显示的响应案例数据为:
    ```
    {
        "success": true,
        "result": "测试的字符串"
    }
    ```

#### Swagger数据模型

在每个app的__init__.py文件中,可以使用以下配置项输出该应用下的数据模型。

- `DJANGO_APIVIEW_SWAGGER_EXPORT_ALL_MODELS = True`,表示是否将该应用下的所有数据库模型输出为swagger-ui数据模型。True表示输出所有数据模型。False表示不输出所有模型。默认为False,表示不输出。
- `DJANGO_APIVIEW_SWAGGER_EXPORT_MODELS = []`,表示输出列表中指定的数据模型。数据模型可以为Django的数据库模型,也可以是Django的表单。使用类引用路径,如:`django_apiview_example.forms.EchoForm`。


#### Swagger其它说明

1. 接口的简述是docstring的第一行。
1. 接口的详细描述是docstring中分割符以上的所有字符串。
1. docstring分割符是指8个以的连续-号字符串。建议将@methods/@parameter/@response等定义放在分割符以后。

## 业务数据封装协议

django-apiview提供自带了多种可供使用的业务数据封装协议。默认为SimpleJsonResultPacker。

### SimpleJsonResultPacker

正确的响应:

```
{
    "success": true,
    "result": <any>
}
```

- success=true,表示业务逻辑处理正确完成。
- result,表示业务逻辑正确完成的情况下返回的有效数据。

错误的响应:

```
{
    "success": false,
    "error": {
        "code": <error_code>
        "message": <error_message>
    }
}
```

- success=false,表示业务逻辑处理异常。
- error,表示具体的错误信息。
    - error.code表示错误码。
    - error.message表示错误原因。
- 一个设计良好的系统,不同原因的错误应该使用不同的错误码,且一个错误码总是对应相同的错误原因。
- 错误原因应该有模板化支持,在保持错误原因整体信息不变的情况下,可以适当填充不同的字段名等。

### SafeJsonResultPacker

在SimpleJsonResultPacker的基础上,进行数据加密。

{
    "encryptedPassword": "xxx",
    "encryptedData": "xxx",
}

- `encryptedPassword`,在随机生成的本次加密密码的RSA加密结果。
- `encryptedData`,在SimpleJsonResultPacker业务数据封装序列化结果,使用本次加密密码进行aes加密的结果。
- 系统在生成加密数据时,必须知道数据接收端的RSA公钥。
- 系统接收端必须能获取到自己的RSA私钥。

### DeetrResultPacker

```
{
    "data": <any>,
    "errcode": 0,
    "errmsg": "OK",
    "time": "2022-09-10 23:09:33",
    "reqid": "67aa6f147d074c2c8bed121c1994f80d",
}
```

- data,表示有效的业务数据。任意可json序列化的数据。如果业务逻辑处理异常,则将data置None或空字符串。特殊场景下,也允许逻辑错误时,使用data字段返回错误相关数据。但错误信息一般不在本字段返回。
- errcode,表示业务逻辑错误码。0表示业务逻辑处理正常,非0表示业务逻辑异常。
- errmsg,表示业务逻辑处理错误信息。如果业务逻辑处理正常则建议返回常量OK。
- time,接口数据的生成时间。推荐使用用户可读的字符串格式,方便用户调试之用。
- reqid,请求的流水号。推荐在nginx中生成。

### DmrsPacker

```
{
    "data": <any>,
    "message": "OK or <error message>",
    "returnCode": 0,
    "successSign": True,
}
```

- data,表示有效的业务数据。任意可json序列化的数据。如果业务逻辑处理异常,则将data置None或空字符串。特殊场景下,也允许逻辑错误时,使用data字段返回错误相关数据。但错误信息一般不在本字段返回。
- message,表示业务逻辑处理错误信息。如果业务逻辑处理正常则建议返回常量OK。
- returnCode,表示业务逻辑错误码。0表示业务逻辑处理正常,非0表示业务逻辑异常。
- successSign,表示业务逻辑处理是否成功。True表示成功,则data字段为有效业务数据,同时一般returnCode为0,message一般为OK或正常。False表示异常,此时returnCode一般为非0表示错误码,message表示错误信息,同时data一般为空。

## 配置项

以下为可配置在`pro/settings.py`中的配置项。

### Swagger相关配置项

- `DJANGO_APIVIEW_SWAGGER_UI_TITLE = "You App Title"`
- `DJANGO_APIVIEW_SWAGGER_UI_DESCRIPTION = "Your App description"`
- `DJANGO_APIVIEW_SWAGGER_UI_VERSION = "Your APP version"`
- `DJANGO_APIVIEW_SWAGGER_UI_TERMS_OF_SERVICE = "Your App Terms of Service URL"`
- `DJANGO_APIVIEW_SWAGGER_UI_CONTACT_EMAIL = "Your email address"`
- `DJANGO_APIVIEW_SWAGGER_UI_API_HOST = "Your site url"`
- `DJANGO_APIVIEW_SWAGGER_FIELDS = {"SchemaField": ("BaseClass", {"extra_key": "extra_value"})}`
    - `SchemaField`,是在数据模型定义中使用的字段或在数据表单定义中使用的字段。一般是应用使用了自定义的字段才需要在此注册。
    - `BaseClass`,是`django_apiview.swagger_ui.field.SchemaField`子类的全路径。如果你的`SchemaField`指向的类是一个数据模型字段,推荐使用`django_apiview.swagger_ui.field.ModelField`,如果你的类是一个表单字段,推荐使用`django_apiview.swagger_ui.field.FormField`。
    - `extra_key` and `extra_value`,是你额外指定的最终应用到swagger模型字段的属性。一般要求有:type。其它属性根据type而定。具体查看swagger-ui的模型定义规则。

### 接口总体控制

- `DJANGO_APIVIEW_DEFAULT_ALLOW_METHODS = ["get", "post"]`,接口请求方式的允许范围。如果接口没有单独的请求方式控制,则接口允许接收这里所列的所有请求方式。接口可以单独设置允许的请求方式,以突破这里的限制。
- `DJANGO_APIVIEW_PACKER = "django_apiview.pack.SimpleJsonResultPacker"`,业务数据封装协议。默认为:django_apiview.pack.SimpleJsonResultPacker。

### 辅助函数关联控制

#### django_apiview.helpers.auth.check_aclkey关联配置

- `DJANGO_APIVIEW_ACLKEY = ""`,允许的aclkey值。
- `DJANGO_APIVIEW_ACLKEYS = []`,允许的aclkey值列表。两者可以同时生效。一般如果允许设置多个ACLKEY则使用DJANGO_APIVIEW_ACLKEYS,只允许一个ACLKEY则使用DJANGO_APIVIEW_ACLKEYDJANGO_APIVIEW_ACLKEY。


## 版本历史

### v1.0.32

- Swagger认证机制。
- 修正路径参数的问题。

### v1.0.19

- 内部重构。对外API保持兼容的情况下有所增强。
- 提供更多种类的业务数据封装协议。
- 提供更多的辅助装饰器。
- 集成Swagger UI。


### v0.9.29及以下

- 提供apiview基本功能。

            

Raw data

            {
    "_id": null,
    "home_page": "",
    "name": "django-apiview",
    "maintainer": "Zhao JunXin",
    "docs_url": null,
    "requires_python": "",
    "maintainer_email": "zhaojunxin@zencore.cn",
    "keywords": "django-apiview",
    "author": "Zhao JunXin",
    "author_email": "zhaojunxin@zencore.cn",
    "download_url": "https://files.pythonhosted.org/packages/01/ed/dac7c8fe13e7b2a309f10df871aaf4b19cbdad0970af99c8df8513d34384/django-apiview-1.0.32.tar.gz",
    "platform": null,
    "description": "# django-apiview\n\n## \u5b89\u88c5\n\n```\npip install django-apiview\n```\n\n## \u5173\u4e8e\u5176\u5b83\u4f9d\u8d56\u5305\u7684\u8bf4\u660e\n\n- `django-apiview`\u4e2d\u7684`@cache`\u529f\u80fd\u4f9d\u8d56\u4e8e`django-redis`\u5305\u3002\u4f46\u6211\u4eec\u5e76\u672a\u5c06`django-redis`\u5f53\u6210\u6211\u4eec\u7684\u4f9d\u8d56\u5305\uff0c\u56e0\u4e3a\u5f88\u591a\u5e94\u7528\u53ef\u80fd\u4e0d\u4f1a\u4f7f\u7528`@cache`\u529f\u80fd\u3002\u5982\u679c\u4f60\u9700\u8981\u4f7f\u7528`@cache`\u529f\u80fd\uff0c\u5219\u4f60\u9700\u8981\u5c06`django-redis`\u4f5c\u4e3a\u4f60\u7684\u9879\u76ee\u7684\u4f9d\u8d56\u5305\u3002\n- `django_apiview.clients.ApiviewClient`\u4f7f\u7528\u5230\u4e86`requests`\u5305\uff0c\u540c\u7406\uff0c\u6211\u4eec\u4e5f\u6ca1\u6709\u5c06\u5176\u5f53\u6210\u6211\u4eec\u7684\u4f9d\u8d56\u5305\u3002\u5982\u679c\u4f60\u9700\u8981\u4f7f\u7528`django_apiview.clients.ApiviewClient`\uff0c\u4f60\u4e5f\u9700\u8981\u5c06`requests`\u4f5c\u4e3a\u4f60\u7684\u9879\u76ee\u7684\u4f9d\u8d56\u5305\u3002\n\n## \u4f7f\u7528\n\n```\nfrom django_apiview.views import apiview\n\n@apiview\ndef ping():\n    \"\"\"\u603b\u662f\u8fd4\u56de\"pong\"\u5b57\u7b26\u4e32\u5e38\u91cf\u3002\n\n    --------\n    @methods: get\n    @response: 200 OK \"\u6b63\u786e\u7684\u54cd\u5e94\" {{{\n        \"pong\"\n    }}}\n    @response: 200 ERROR \"\u9519\u8bef\u7684\u54cd\u5e94\" {{{\n        {\n            \"code\": 1234,\n            \"message\": \"\u9519\u8bef\u539f\u56e0\u3002\"\n        }\n    }}}\n    \"\"\"\n    return \"pong\"\n\n\n@apiview\n@string_length_limit(\"msg\", max_length=4096, min_length=2)\ndef echo(msg: str):\n    \"\"\"\u603b\u662f\u8fd4\u56de\u4f60\u8f93\u5165\u7684\u5185\u5bb9\u3002\n\n    \u8981\u6c42\u53c2\u6570msg\u7684\u957f\u5ea6\u8303\u56f4\u4e3a\uff1a[2, 4096]\u3002\n\n    --------\n    @methods: post\n    @parameter: body {{{\n        in: body\n        required: true\n        example:\n          msg: \"\u6d4b\u8bd5\u7684\u5b57\u7b26\u4e32\"\n    }}}\n    @response: 200 OK \"\u6b63\u786e\u7684\u54cd\u5e94\" {{{\n        \"\u6d4b\u8bd5\u7684\u5b57\u7b26\u4e32\"\n    }}}\n    @response: 500 ERROR \"\u9519\u8bef\u7684\u54cd\u5e94\" {{{\n        {\n            \"code\": 1234,\n            \"message\": \"\u9519\u8bef\u539f\u56e0\u3002\"\n        }\n    }}}\n    \"\"\"\n    return msg\n```\n\n1. \u4f7f\u7528django-apiview\u5b9a\u4e49\u63a5\u53e3\uff0c\u603b\u662f\u8981\u52a0\u4e0a@apiview\u6ce8\u89e3\uff0c\u5e76\u4e14\u8981\u6c42\u662f\u7b2c\u4e00\u4e2a\u6ce8\u89e3\u3002\n1. \u53ef\u4ee5\u4f7f\u7528\u591a\u4e2a\u8f85\u52a9\u6ce8\u89e3\u6765\u8fdb\u884c\u53c2\u6570\u68c0\u67e5\u548c\u5176\u4ed6\u5404\u7c7b\u68c0\u67e5\u3002\n1. \u63a5\u53e3\u51fd\u6570\u53ea\u8981\u8fd4\u56de\u4e1a\u52a1\u5c42\u6570\u636e\u5373\u53ef\uff0cdjango-apiview\u4f1a\u5bf9\u5176\u8fdb\u884c\u5e8f\u5217\u5316\u548c\u4e1a\u52a1\u534f\u8bae\u5c01\u88c5\u3002\n1. \u652f\u6301swagger\u63a5\u53e3\u7ba1\u7406\u754c\u9762\u81ea\u52a8\u751f\u6210\u3002\u6240\u6709\u9700\u8981\u5728swagger\u63a5\u53e3\u7ba1\u7406\u754c\u9762\u4e2d\u663e\u793a\u7684\u63a5\u53e3\uff0c\u9700\u8981\u5728\u5176docstring\u4e2d\u6dfb\u52a0swagger\u914d\u7f6e\u3002\n\n## \u8f85\u52a9\u6ce8\u89e3\n\n- django_apiview.helpers.auth\n    - check_aclkey: \u68c0\u67e5\u8bf7\u6c42\u5934/\u8bf7\u6c42\u53c2\u6570/\u8bf7\u6c42\u6570\u636e\u4e2d\u662f\u5426\u6709aclkey\u5b57\u6bb5\uff0c\u5e76\u4e14aclkey\u5b57\u6bb5\u662f\u5426\u6709\u6548\u3002\n- django_apiview.helpers.cache\n    - cache: \u63a5\u53e3\u7f13\u5b58\u652f\u6301\u3002\u652f\u6301\u6a21\u578b\u6570\u636e\u53d8\u52a8\u8054\u52a8\u7f13\u5b58\u6e05\u7406\u3002\n- django_apiview.helpers.cipher\n    - rsa_decrypt: \u5bc6\u7801\u5b57\u6bb5rsa\u52a0\u89e3\u5bc6\u3002\n    - decode_encrypted_data: \u4e1a\u52a1\u6570\u636e\u6574\u4f53rsa\u52a0\u89e3\u5bc6\u3002\n- django_apiview.helpers.request_methods\uff08\u5982\u679c\u4e0d\u6dfb\u52a0\u4efb\u4f55\u8bf7\u6c42\u65b9\u5f0f\u63a7\u5236\uff0c\u5219\u6839\u636e\u5168\u5c40\u8bbe\u7f6e\u5141\u8bb8\u5168\u90e8\uff09\n    - allow_get: \u5141\u8bb8get\u8bf7\u6c42\u65b9\u5f0f\u3002\n    - allow_post: \u5141\u8bb8post\u8bf7\u6c42\u65b9\u5f0f\u3002\n    - allow_put: \u5141\u8bb8put\u8bf7\u6c42\u65b9\u5f0f\u3002\n    - allow_delete: \u5141\u8bb8delete\u8bf7\u6c42\u65b9\u5f0f\u3002\n    - allow_patch: \u5141\u8bb8patch\u8bf7\u6c42\u65b9\u5f0f\u3002\n    - allow_head: \u5141\u8bb8head\u8bf7\u6c42\u65b9\u5f0f\u3002\n    - allow_options: \u5141\u8bb8options\u8bf7\u6c42\u65b9\u5f0f\u3002\n- django_apiview.helpers.transformer\n    - body_alias: \u5c06body\u6574\u4f53\u8d4b\u7ed9\u65b0\u7684\u53d8\u91cf\n    - cookie_variable: \u5c06cookie\u503c\u8d4b\u7ed9\u65b0\u7684\u53d8\u91cf\n    - meta_variable: \u5c06meta\u503c\u8d4b\u7ed9\u65b0\u7684\u53d8\u91cf\n- django_apiview.helpers.validators\n    - requires: \u8bbe\u7f6e\u5fc5\u586b\u53c2\u6570\u3002\n    - choices: \u8bbe\u7f6e\u53c2\u6570\u9009\u9879\u8303\u56f4\u3002\n    - between: \u8bbe\u7f6e\u53c2\u6570\u53d6\u503c\u8303\u56f4\u3002\n    - string_length_limit: \u8bbe\u7f6e\u53c2\u6570\u957f\u5ea6\u8303\u56f4\u3002\n\n## Swagger\u96c6\u6210\n\n### Swagger\u96c6\u6210\u6548\u679c\u56fe\n\n![django_apiview swagger\u96c6\u6210\u6548\u679c](https://github.com/zencore-dobetter/pypi-images/raw/main/django-apiview/swagger.png)\n\n### Swagger\u96c6\u6210\n\n*pro/settings.py*\n```\nINSTALLED_APPS = [\n    ...\n    \"django_static_swagger_ui\",\n    \"django_apiview\",\n    ...\n]\n```\n\n*pro/urls.py*\n\n```\nfrom django.urls import path\nfrom django.urls import include\n\nurlpatterns = [\n    ...\n    path('apiview/', include(\"django_apiview.urls\")),\n    ...\n]\n```\n\n- \u914d\u7f6e\u5982\u4e0a\u3002\u8bbf\u95ee\uff1ahttp://127.0.0.1:8000/apiview/swagger-ui.html\u3002\n- \u5982\u4f55\u63a7\u5236swagger\u7684\u8f93\u51fa\u8303\u56f4\u4ee5\u53ca\u5982\u4f55\u914d\u7f6e\u63a5\u53e3\u7684swagger\u8f93\u51fa\u8be6\u89c1\u4e0b\u9762\u8bf4\u660e\u3002\n\n### Swagger Docstring\u89c4\u5219\n\n#### parameter\u89c4\u5219\n\n```\n@parameter: <parameter_name> {{{\n    <parameter_attributes>\n}}}\n```\n\n- parameter_name: \u5b57\u7b26\u4e32\uff0c\u53d8\u91cf\u540d\u3002\n- parameter_attributes: json\u6216yaml\u683c\u5f0f\u3002\u9075\u5faaswagger-ui\u7684\u53c2\u6570\u8bed\u6cd5\u3002\u90e8\u5206\u53c2\u6570\u5b57\u6bb5\u5982\u4e0b\uff1a\n    - `in: [body, path, query, formData]` \u8868\u793a\u53c2\u6570\u6765\u6e90\n    - `required: true/false` \u8868\u793a\u5b57\u6bb5\u662f\u5426\u5fc5\u586b\n    - `example:` \u8868\u793a\u53c2\u6570\u793a\u4f8b\n    - `schema:`\n        - `$ref: #/components/schemas/ModelName` \u8868\u793a\u53c2\u6570\u6a21\u578b\n    - `type: integer/string` \u8868\u793a\u53c2\u6570\u7c7b\u578b\n- `@parameter:`\uff0c\u53ef\u4ee5\u591a\u6b21\u4f7f\u7528\uff0c\u663e\u793a\u591a\u4e2a\u53c2\u6570\u3002\u5404\u53c2\u6570\u7684in\u5c5e\u6027\u53ef\u4ee5\u4e0d\u540c\uff0c\u8868\u793a\u53c2\u6570\u53ef\u4ee5\u6709\u4e0d\u540c\u7684\u6765\u6e90\u3002\n- `in: body`\uff0c\u8f83\u4e3a\u7279\u6b8a\uff0c\u4e00\u822c\u53ea\u6709\u4e00\u4e2a\uff0c\u8868\u793a\u4ee5json payload\u5f62\u5f0f\u63d0\u4ea4\u7684\u6570\u636e\u6574\u4f53\u3002\n\n\u4f7f\u7528\u4e3e\u4f8b\uff1a\n\n```\n@parameter: body {{{\n    in: body\n    required: true\n    example:\n        msg: \"Example Message\"\n}}}\n```\n\n- `in: body`\uff0c\u8868\u793a\u53c2\u6570\u4f7f\u7528json payload\u5f62\u5f0f\u63d0\u4ea4\u3002\n- `required: true`\uff0c\u8868\u793a\u53c2\u6570\u662f\u5fc5\u586b\u7684\u3002\n- `example:\\n    msg: \"Example Message\"`\uff0c\u8868\u793a\u53c2\u6570\u793a\u4f8b\uff0c\u5c06\u663e\u793a\u5728swagger\u7684\u53c2\u6570\u8f93\u5165\u6846\u4e2d\u3002\n\n#### response\u89c4\u5219\n\n```\n@response: <http_status_code> <respones_status> <respones_description> {{{\n    <response_body>\n}}}\n```\n\n- `http_status_code`\uff0c\u8868\u793ahttp\u54cd\u5e94\u72b6\u6001\u7801\u3002\u4e00\u822c\u4e3a200\uff0c404\uff0c500\u7b49\u3002\u9664\u975e\u7cfb\u7edf\u7ea7\u9519\u8bef\uff0c\u6b63\u786e\u54cd\u5e94\u548c\u4e00\u822c\u4e1a\u52a1\u903b\u8f91\u9519\u8bef\u63a8\u8350\u4f7f\u7528200\u3002\n- `respones_status`\uff0c\u53d6\u503c\u4e3aOK\u6216ERROR\uff0c\u8868\u793a\u4e1a\u52a1\u72b6\u6001\u3002OK\u8868\u793a\u4e1a\u52a1\u5904\u7406\u6b63\u786e\u3002ERROR\u8868\u793a\u4e1a\u52a1\u5904\u7406\u5f02\u5e38\u3002\n- `respones_description`\uff0c\u8868\u793a\u672c\u54cd\u5e94\u793a\u4f8b\u7684\u4e1a\u52a1\u8bf4\u660e\u3002\n- `response_body`\uff0c\u8868\u793a\u793a\u4f8b\u7684\u54cd\u5e94\u4f53\u3002\u53ea\u9700\u8981\u663e\u793a\u6709\u6548\u7684\u4e1a\u52a1\u6570\u636e\u90e8\u5206\u5373\u53ef\u3002django-apiview\u6216\u81ea\u52a8\u8fdb\u884c\u4e1a\u52a1\u6570\u636e\u7684\u5c01\u88c5\uff0c\u6700\u7ec8\u663e\u793a\u4e3a\u5b8c\u6574\u7684\u54cd\u5e94\u6570\u636e\u5305\u3002\n- `@response`\uff0c\u53ef\u4ee5\u591a\u6b21\u4f7f\u7528\uff0c\u53ef\u4ee5\u7528\u6765\u8868\u793a\u5728\u4e0d\u540c\u60c5\u51b5\u4e0b\u7684\u54cd\u5e94\u3002\n\n\u4f7f\u7528\u4e3e\u4f8b\uff1a\n\n```\n@response: 200 OK \"\u6b63\u786e\u7684\u54cd\u5e94\" {{{\n    \"\u6d4b\u8bd5\u7684\u5b57\u7b26\u4e32\"\n}}}\n```\n\n- `200`\uff0c\u8868\u793ahttp\u72b6\u6001\u7801\u4e3a\u6b63\u786e\u7684http\u54cd\u5e94\u3002\n- `OK`\uff0c\u8868\u793a\u4e1a\u52a1\u903b\u8f91\u5904\u7406\u6b63\u786e\u5b8c\u6210\u3002\n- `\u6b63\u786e\u7684\u54cd\u5e94`\uff0c\u8868\u793a\u4ee5\u4e0b\u7684\u54cd\u5e94\u672a\u4f8b\u4e3a\u6b63\u5e38\u60c5\u51b5\u4e0b\u7684\u54cd\u5e94\u6570\u636e\u3002\n- `\u6d4b\u8bd5\u7684\u5b57\u7b26\u4e32`\uff0c\u8868\u793a\u8fd4\u56de\u7684\u6709\u6548\u4e1a\u52a1\u6570\u636e\u5185\u5bb9\u3002\u5982\u679c\u4f7f\u7528SimpleJsonResultPacker\u4e1a\u52a1\u5c01\u88c5\u534f\u8bae\uff0c\u5219\u6700\u7ec8\u663e\u793a\u7684\u54cd\u5e94\u6848\u4f8b\u6570\u636e\u4e3a\uff1a\n    ```\n    {\n        \"success\": true,\n        \"result\": \"\u6d4b\u8bd5\u7684\u5b57\u7b26\u4e32\"\n    }\n    ```\n\n#### Swagger\u6570\u636e\u6a21\u578b\n\n\u5728\u6bcf\u4e2aapp\u7684__init__.py\u6587\u4ef6\u4e2d\uff0c\u53ef\u4ee5\u4f7f\u7528\u4ee5\u4e0b\u914d\u7f6e\u9879\u8f93\u51fa\u8be5\u5e94\u7528\u4e0b\u7684\u6570\u636e\u6a21\u578b\u3002\n\n- `DJANGO_APIVIEW_SWAGGER_EXPORT_ALL_MODELS = True`\uff0c\u8868\u793a\u662f\u5426\u5c06\u8be5\u5e94\u7528\u4e0b\u7684\u6240\u6709\u6570\u636e\u5e93\u6a21\u578b\u8f93\u51fa\u4e3aswagger-ui\u6570\u636e\u6a21\u578b\u3002True\u8868\u793a\u8f93\u51fa\u6240\u6709\u6570\u636e\u6a21\u578b\u3002False\u8868\u793a\u4e0d\u8f93\u51fa\u6240\u6709\u6a21\u578b\u3002\u9ed8\u8ba4\u4e3aFalse\uff0c\u8868\u793a\u4e0d\u8f93\u51fa\u3002\n- `DJANGO_APIVIEW_SWAGGER_EXPORT_MODELS = []`\uff0c\u8868\u793a\u8f93\u51fa\u5217\u8868\u4e2d\u6307\u5b9a\u7684\u6570\u636e\u6a21\u578b\u3002\u6570\u636e\u6a21\u578b\u53ef\u4ee5\u4e3aDjango\u7684\u6570\u636e\u5e93\u6a21\u578b\uff0c\u4e5f\u53ef\u4ee5\u662fDjango\u7684\u8868\u5355\u3002\u4f7f\u7528\u7c7b\u5f15\u7528\u8def\u5f84\uff0c\u5982\uff1a`django_apiview_example.forms.EchoForm`\u3002\n\n\n#### Swagger\u5176\u5b83\u8bf4\u660e\n\n1. \u63a5\u53e3\u7684\u7b80\u8ff0\u662fdocstring\u7684\u7b2c\u4e00\u884c\u3002\n1. \u63a5\u53e3\u7684\u8be6\u7ec6\u63cf\u8ff0\u662fdocstring\u4e2d\u5206\u5272\u7b26\u4ee5\u4e0a\u7684\u6240\u6709\u5b57\u7b26\u4e32\u3002\n1. docstring\u5206\u5272\u7b26\u662f\u63078\u4e2a\u4ee5\u7684\u8fde\u7eed-\u53f7\u5b57\u7b26\u4e32\u3002\u5efa\u8bae\u5c06@methods/@parameter/@response\u7b49\u5b9a\u4e49\u653e\u5728\u5206\u5272\u7b26\u4ee5\u540e\u3002\n\n## \u4e1a\u52a1\u6570\u636e\u5c01\u88c5\u534f\u8bae\n\ndjango-apiview\u63d0\u4f9b\u81ea\u5e26\u4e86\u591a\u79cd\u53ef\u4f9b\u4f7f\u7528\u7684\u4e1a\u52a1\u6570\u636e\u5c01\u88c5\u534f\u8bae\u3002\u9ed8\u8ba4\u4e3aSimpleJsonResultPacker\u3002\n\n### SimpleJsonResultPacker\n\n\u6b63\u786e\u7684\u54cd\u5e94:\n\n```\n{\n    \"success\": true,\n    \"result\": <any>\n}\n```\n\n- success=true\uff0c\u8868\u793a\u4e1a\u52a1\u903b\u8f91\u5904\u7406\u6b63\u786e\u5b8c\u6210\u3002\n- result\uff0c\u8868\u793a\u4e1a\u52a1\u903b\u8f91\u6b63\u786e\u5b8c\u6210\u7684\u60c5\u51b5\u4e0b\u8fd4\u56de\u7684\u6709\u6548\u6570\u636e\u3002\n\n\u9519\u8bef\u7684\u54cd\u5e94\uff1a\n\n```\n{\n    \"success\": false,\n    \"error\": {\n        \"code\": <error_code>\n        \"message\": <error_message>\n    }\n}\n```\n\n- success=false\uff0c\u8868\u793a\u4e1a\u52a1\u903b\u8f91\u5904\u7406\u5f02\u5e38\u3002\n- error\uff0c\u8868\u793a\u5177\u4f53\u7684\u9519\u8bef\u4fe1\u606f\u3002\n    - error.code\u8868\u793a\u9519\u8bef\u7801\u3002\n    - error.message\u8868\u793a\u9519\u8bef\u539f\u56e0\u3002\n- \u4e00\u4e2a\u8bbe\u8ba1\u826f\u597d\u7684\u7cfb\u7edf\uff0c\u4e0d\u540c\u539f\u56e0\u7684\u9519\u8bef\u5e94\u8be5\u4f7f\u7528\u4e0d\u540c\u7684\u9519\u8bef\u7801\uff0c\u4e14\u4e00\u4e2a\u9519\u8bef\u7801\u603b\u662f\u5bf9\u5e94\u76f8\u540c\u7684\u9519\u8bef\u539f\u56e0\u3002\n- \u9519\u8bef\u539f\u56e0\u5e94\u8be5\u6709\u6a21\u677f\u5316\u652f\u6301\uff0c\u5728\u4fdd\u6301\u9519\u8bef\u539f\u56e0\u6574\u4f53\u4fe1\u606f\u4e0d\u53d8\u7684\u60c5\u51b5\u4e0b\uff0c\u53ef\u4ee5\u9002\u5f53\u586b\u5145\u4e0d\u540c\u7684\u5b57\u6bb5\u540d\u7b49\u3002\n\n### SafeJsonResultPacker\n\n\u5728SimpleJsonResultPacker\u7684\u57fa\u7840\u4e0a\uff0c\u8fdb\u884c\u6570\u636e\u52a0\u5bc6\u3002\n\n{\n    \"encryptedPassword\": \"xxx\",\n    \"encryptedData\": \"xxx\",\n}\n\n- `encryptedPassword`\uff0c\u5728\u968f\u673a\u751f\u6210\u7684\u672c\u6b21\u52a0\u5bc6\u5bc6\u7801\u7684RSA\u52a0\u5bc6\u7ed3\u679c\u3002\n- `encryptedData`\uff0c\u5728SimpleJsonResultPacker\u4e1a\u52a1\u6570\u636e\u5c01\u88c5\u5e8f\u5217\u5316\u7ed3\u679c\uff0c\u4f7f\u7528\u672c\u6b21\u52a0\u5bc6\u5bc6\u7801\u8fdb\u884caes\u52a0\u5bc6\u7684\u7ed3\u679c\u3002\n- \u7cfb\u7edf\u5728\u751f\u6210\u52a0\u5bc6\u6570\u636e\u65f6\uff0c\u5fc5\u987b\u77e5\u9053\u6570\u636e\u63a5\u6536\u7aef\u7684RSA\u516c\u94a5\u3002\n- \u7cfb\u7edf\u63a5\u6536\u7aef\u5fc5\u987b\u80fd\u83b7\u53d6\u5230\u81ea\u5df1\u7684RSA\u79c1\u94a5\u3002\n\n### DeetrResultPacker\n\n```\n{\n    \"data\": <any>,\n    \"errcode\": 0,\n    \"errmsg\": \"OK\",\n    \"time\": \"2022-09-10 23:09:33\",\n    \"reqid\": \"67aa6f147d074c2c8bed121c1994f80d\",\n}\n```\n\n- data\uff0c\u8868\u793a\u6709\u6548\u7684\u4e1a\u52a1\u6570\u636e\u3002\u4efb\u610f\u53efjson\u5e8f\u5217\u5316\u7684\u6570\u636e\u3002\u5982\u679c\u4e1a\u52a1\u903b\u8f91\u5904\u7406\u5f02\u5e38\uff0c\u5219\u5c06data\u7f6eNone\u6216\u7a7a\u5b57\u7b26\u4e32\u3002\u7279\u6b8a\u573a\u666f\u4e0b\uff0c\u4e5f\u5141\u8bb8\u903b\u8f91\u9519\u8bef\u65f6\uff0c\u4f7f\u7528data\u5b57\u6bb5\u8fd4\u56de\u9519\u8bef\u76f8\u5173\u6570\u636e\u3002\u4f46\u9519\u8bef\u4fe1\u606f\u4e00\u822c\u4e0d\u5728\u672c\u5b57\u6bb5\u8fd4\u56de\u3002\n- errcode\uff0c\u8868\u793a\u4e1a\u52a1\u903b\u8f91\u9519\u8bef\u7801\u30020\u8868\u793a\u4e1a\u52a1\u903b\u8f91\u5904\u7406\u6b63\u5e38\uff0c\u975e0\u8868\u793a\u4e1a\u52a1\u903b\u8f91\u5f02\u5e38\u3002\n- errmsg\uff0c\u8868\u793a\u4e1a\u52a1\u903b\u8f91\u5904\u7406\u9519\u8bef\u4fe1\u606f\u3002\u5982\u679c\u4e1a\u52a1\u903b\u8f91\u5904\u7406\u6b63\u5e38\u5219\u5efa\u8bae\u8fd4\u56de\u5e38\u91cfOK\u3002\n- time\uff0c\u63a5\u53e3\u6570\u636e\u7684\u751f\u6210\u65f6\u95f4\u3002\u63a8\u8350\u4f7f\u7528\u7528\u6237\u53ef\u8bfb\u7684\u5b57\u7b26\u4e32\u683c\u5f0f\uff0c\u65b9\u4fbf\u7528\u6237\u8c03\u8bd5\u4e4b\u7528\u3002\n- reqid\uff0c\u8bf7\u6c42\u7684\u6d41\u6c34\u53f7\u3002\u63a8\u8350\u5728nginx\u4e2d\u751f\u6210\u3002\n\n### DmrsPacker\n\n```\n{\n    \"data\": <any>,\n    \"message\": \"OK or <error message>\",\n    \"returnCode\": 0,\n    \"successSign\": True,\n}\n```\n\n- data\uff0c\u8868\u793a\u6709\u6548\u7684\u4e1a\u52a1\u6570\u636e\u3002\u4efb\u610f\u53efjson\u5e8f\u5217\u5316\u7684\u6570\u636e\u3002\u5982\u679c\u4e1a\u52a1\u903b\u8f91\u5904\u7406\u5f02\u5e38\uff0c\u5219\u5c06data\u7f6eNone\u6216\u7a7a\u5b57\u7b26\u4e32\u3002\u7279\u6b8a\u573a\u666f\u4e0b\uff0c\u4e5f\u5141\u8bb8\u903b\u8f91\u9519\u8bef\u65f6\uff0c\u4f7f\u7528data\u5b57\u6bb5\u8fd4\u56de\u9519\u8bef\u76f8\u5173\u6570\u636e\u3002\u4f46\u9519\u8bef\u4fe1\u606f\u4e00\u822c\u4e0d\u5728\u672c\u5b57\u6bb5\u8fd4\u56de\u3002\n- message\uff0c\u8868\u793a\u4e1a\u52a1\u903b\u8f91\u5904\u7406\u9519\u8bef\u4fe1\u606f\u3002\u5982\u679c\u4e1a\u52a1\u903b\u8f91\u5904\u7406\u6b63\u5e38\u5219\u5efa\u8bae\u8fd4\u56de\u5e38\u91cfOK\u3002\n- returnCode\uff0c\u8868\u793a\u4e1a\u52a1\u903b\u8f91\u9519\u8bef\u7801\u30020\u8868\u793a\u4e1a\u52a1\u903b\u8f91\u5904\u7406\u6b63\u5e38\uff0c\u975e0\u8868\u793a\u4e1a\u52a1\u903b\u8f91\u5f02\u5e38\u3002\n- successSign\uff0c\u8868\u793a\u4e1a\u52a1\u903b\u8f91\u5904\u7406\u662f\u5426\u6210\u529f\u3002True\u8868\u793a\u6210\u529f\uff0c\u5219data\u5b57\u6bb5\u4e3a\u6709\u6548\u4e1a\u52a1\u6570\u636e\uff0c\u540c\u65f6\u4e00\u822creturnCode\u4e3a0\uff0cmessage\u4e00\u822c\u4e3aOK\u6216\u6b63\u5e38\u3002False\u8868\u793a\u5f02\u5e38\uff0c\u6b64\u65f6returnCode\u4e00\u822c\u4e3a\u975e0\u8868\u793a\u9519\u8bef\u7801\uff0cmessage\u8868\u793a\u9519\u8bef\u4fe1\u606f\uff0c\u540c\u65f6data\u4e00\u822c\u4e3a\u7a7a\u3002\n\n## \u914d\u7f6e\u9879\n\n\u4ee5\u4e0b\u4e3a\u53ef\u914d\u7f6e\u5728`pro/settings.py`\u4e2d\u7684\u914d\u7f6e\u9879\u3002\n\n### Swagger\u76f8\u5173\u914d\u7f6e\u9879\n\n- `DJANGO_APIVIEW_SWAGGER_UI_TITLE = \"You App Title\"`\n- `DJANGO_APIVIEW_SWAGGER_UI_DESCRIPTION = \"Your App description\"`\n- `DJANGO_APIVIEW_SWAGGER_UI_VERSION = \"Your APP version\"`\n- `DJANGO_APIVIEW_SWAGGER_UI_TERMS_OF_SERVICE = \"Your App Terms of Service URL\"`\n- `DJANGO_APIVIEW_SWAGGER_UI_CONTACT_EMAIL = \"Your email address\"`\n- `DJANGO_APIVIEW_SWAGGER_UI_API_HOST = \"Your site url\"`\n- `DJANGO_APIVIEW_SWAGGER_FIELDS = {\"SchemaField\": (\"BaseClass\", {\"extra_key\": \"extra_value\"})}`\n    - `SchemaField`\uff0c\u662f\u5728\u6570\u636e\u6a21\u578b\u5b9a\u4e49\u4e2d\u4f7f\u7528\u7684\u5b57\u6bb5\u6216\u5728\u6570\u636e\u8868\u5355\u5b9a\u4e49\u4e2d\u4f7f\u7528\u7684\u5b57\u6bb5\u3002\u4e00\u822c\u662f\u5e94\u7528\u4f7f\u7528\u4e86\u81ea\u5b9a\u4e49\u7684\u5b57\u6bb5\u624d\u9700\u8981\u5728\u6b64\u6ce8\u518c\u3002\n    - `BaseClass`\uff0c\u662f`django_apiview.swagger_ui.field.SchemaField`\u5b50\u7c7b\u7684\u5168\u8def\u5f84\u3002\u5982\u679c\u4f60\u7684`SchemaField`\u6307\u5411\u7684\u7c7b\u662f\u4e00\u4e2a\u6570\u636e\u6a21\u578b\u5b57\u6bb5\uff0c\u63a8\u8350\u4f7f\u7528`django_apiview.swagger_ui.field.ModelField`\uff0c\u5982\u679c\u4f60\u7684\u7c7b\u662f\u4e00\u4e2a\u8868\u5355\u5b57\u6bb5\uff0c\u63a8\u8350\u4f7f\u7528`django_apiview.swagger_ui.field.FormField`\u3002\n    - `extra_key` and `extra_value`\uff0c\u662f\u4f60\u989d\u5916\u6307\u5b9a\u7684\u6700\u7ec8\u5e94\u7528\u5230swagger\u6a21\u578b\u5b57\u6bb5\u7684\u5c5e\u6027\u3002\u4e00\u822c\u8981\u6c42\u6709\uff1atype\u3002\u5176\u5b83\u5c5e\u6027\u6839\u636etype\u800c\u5b9a\u3002\u5177\u4f53\u67e5\u770bswagger-ui\u7684\u6a21\u578b\u5b9a\u4e49\u89c4\u5219\u3002\n\n### \u63a5\u53e3\u603b\u4f53\u63a7\u5236\n\n- `DJANGO_APIVIEW_DEFAULT_ALLOW_METHODS = [\"get\", \"post\"]`\uff0c\u63a5\u53e3\u8bf7\u6c42\u65b9\u5f0f\u7684\u5141\u8bb8\u8303\u56f4\u3002\u5982\u679c\u63a5\u53e3\u6ca1\u6709\u5355\u72ec\u7684\u8bf7\u6c42\u65b9\u5f0f\u63a7\u5236\uff0c\u5219\u63a5\u53e3\u5141\u8bb8\u63a5\u6536\u8fd9\u91cc\u6240\u5217\u7684\u6240\u6709\u8bf7\u6c42\u65b9\u5f0f\u3002\u63a5\u53e3\u53ef\u4ee5\u5355\u72ec\u8bbe\u7f6e\u5141\u8bb8\u7684\u8bf7\u6c42\u65b9\u5f0f\uff0c\u4ee5\u7a81\u7834\u8fd9\u91cc\u7684\u9650\u5236\u3002\n- `DJANGO_APIVIEW_PACKER = \"django_apiview.pack.SimpleJsonResultPacker\"`\uff0c\u4e1a\u52a1\u6570\u636e\u5c01\u88c5\u534f\u8bae\u3002\u9ed8\u8ba4\u4e3a\uff1adjango_apiview.pack.SimpleJsonResultPacker\u3002\n\n### \u8f85\u52a9\u51fd\u6570\u5173\u8054\u63a7\u5236\n\n#### django_apiview.helpers.auth.check_aclkey\u5173\u8054\u914d\u7f6e\n\n- `DJANGO_APIVIEW_ACLKEY = \"\"`\uff0c\u5141\u8bb8\u7684aclkey\u503c\u3002\n- `DJANGO_APIVIEW_ACLKEYS = []`\uff0c\u5141\u8bb8\u7684aclkey\u503c\u5217\u8868\u3002\u4e24\u8005\u53ef\u4ee5\u540c\u65f6\u751f\u6548\u3002\u4e00\u822c\u5982\u679c\u5141\u8bb8\u8bbe\u7f6e\u591a\u4e2aACLKEY\u5219\u4f7f\u7528DJANGO_APIVIEW_ACLKEYS\uff0c\u53ea\u5141\u8bb8\u4e00\u4e2aACLKEY\u5219\u4f7f\u7528DJANGO_APIVIEW_ACLKEYDJANGO_APIVIEW_ACLKEY\u3002\n\n\n## \u7248\u672c\u5386\u53f2\n\n### v1.0.32\n\n- Swagger\u8ba4\u8bc1\u673a\u5236\u3002\n- \u4fee\u6b63\u8def\u5f84\u53c2\u6570\u7684\u95ee\u9898\u3002\n\n### v1.0.19\n\n- \u5185\u90e8\u91cd\u6784\u3002\u5bf9\u5916API\u4fdd\u6301\u517c\u5bb9\u7684\u60c5\u51b5\u4e0b\u6709\u6240\u589e\u5f3a\u3002\n- \u63d0\u4f9b\u66f4\u591a\u79cd\u7c7b\u7684\u4e1a\u52a1\u6570\u636e\u5c01\u88c5\u534f\u8bae\u3002\n- \u63d0\u4f9b\u66f4\u591a\u7684\u8f85\u52a9\u88c5\u9970\u5668\u3002\n- \u96c6\u6210Swagger UI\u3002\n\n\n### v0.9.29\u53ca\u4ee5\u4e0b\n\n- \u63d0\u4f9bapiview\u57fa\u672c\u529f\u80fd\u3002\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "A set of django tools to help you create JSON service..",
    "version": "1.0.32",
    "project_urls": null,
    "split_keywords": [
        "django-apiview"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "0b9d64fc4664cb89f93a5af6ede82093ed75c1674ad35ace0732ef4e9498ff51",
                "md5": "f009231d0f76170de15b30208f7eff3f",
                "sha256": "b3fed8431b84d192ac8c8dd93fa5d94194655f429416c50287c917f8ca054c0a"
            },
            "downloads": -1,
            "filename": "django_apiview-1.0.32-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "f009231d0f76170de15b30208f7eff3f",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": null,
            "size": 35671,
            "upload_time": "2023-09-13T07:13:46",
            "upload_time_iso_8601": "2023-09-13T07:13:46.780627Z",
            "url": "https://files.pythonhosted.org/packages/0b/9d/64fc4664cb89f93a5af6ede82093ed75c1674ad35ace0732ef4e9498ff51/django_apiview-1.0.32-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "01eddac7c8fe13e7b2a309f10df871aaf4b19cbdad0970af99c8df8513d34384",
                "md5": "133f34be435ecec80fd0590f86e0e0f8",
                "sha256": "d2c02c4bee589d63ccee4ec1e1aa161d922bee53b7eb591f458dcada038e3565"
            },
            "downloads": -1,
            "filename": "django-apiview-1.0.32.tar.gz",
            "has_sig": false,
            "md5_digest": "133f34be435ecec80fd0590f86e0e0f8",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": null,
            "size": 32004,
            "upload_time": "2023-09-13T07:13:49",
            "upload_time_iso_8601": "2023-09-13T07:13:49.036004Z",
            "url": "https://files.pythonhosted.org/packages/01/ed/dac7c8fe13e7b2a309f10df871aaf4b19cbdad0970af99c8df8513d34384/django-apiview-1.0.32.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2023-09-13 07:13:49",
    "github": false,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "lcname": "django-apiview"
}
        
Elapsed time: 0.17201s