问题描述
我正在使用 drf-yasg
(Django REST Framework - Yet Another Swagger Generator)为我的 RESTful API 生成文档,但它并没有完全按照我的意愿行事。我认为将 read_only
和 write_only
属性设置为 True
会隐藏文档中的字段,因为它们从请求和响应正文中被省略,但事实并非如此。我没有看到任何在装饰器中定义模式的例子,甚至只是隐藏一个字段,但如果我能学会如何做其中一件事情,我就会处于良好状态。
# serializers.py
class TokensSerializer(serializers.Serializer):
"""
Serializes access and refresh tokens for responses to a logged-in user.
"""
username = serializers.CharField(max_length=64,write_only=True)
access = serializers.CharField(max_length=4096,read_only=True)
refresh = serializers.CharField(max_length=4096,read_only=True)
# ...
class LoginSerializer(serializers.ModelSerializer):
"""
Serializes username,email,password,and tokens to allow for logging in.
"""
class Meta():
model = User
fields = ['username','email','password','tokens']
username = serializers.CharField(max_length=64)
email = serializers.CharField(max_length=254,read_only=True)
password = serializers.CharField(
min_length=8,max_length=64,write_only=True)
tokens = TokensSerializer(read_only=True)
# ...
这些序列化程序分别生成 Tokens
和 Login
模型,它们以以下 .json 和 .yaml 格式定义:
{
"deFinitions": {
"Tokens": {
"required": ["username"],"type": "object","properties": {
"username": {
"title": "Username","type": "string","maxLength": 64,"minLength": 1
},"access": {
"title": "Access","readOnly": true,"maxLength": 4096,"refresh": {
"title": "Refresh","minLength": 1
}
}
},"Login": {
"required": ["username","password"],"email": {
"title": "Email","maxLength": 254,"password": {
"title": "Password","minLength": 8
},"tokens": {
"$ref": "#/deFinitions/Tokens"
}
}
}
}
}
deFinitions:
Tokens:
required:
- username
type: object
properties:
username:
title: Username
type: string
maxLength: 64
minLength: 1
access:
title: Access
type: string
readOnly: true
maxLength: 4096
minLength: 1
refresh:
title: Refresh
type: string
readOnly: true
maxLength: 4096
minLength: 1
Login:
required:
- username
- password
type: object
properties:
username:
title: Username
type: string
maxLength: 64
minLength: 1
email:
title: Email
type: string
readOnly: true
maxLength: 254
minLength: 1
password:
title: Password
type: string
maxLength: 64
minLength: 8
tokens:
$ref: '#/deFinitions/Tokens'
然而,这些并不适合每个请求或响应主体,我想要么明确定义架构,要么使用省略字段的现有架构。我不知道如何实现后者,但这是我对前者的尝试,这会导致错误:
class LoginView(GenericAPIView):
"""
View for taking in an existing user's credentials and authorizing them if valid or denying access if invalid.
"""
serializer_class = LoginSerializer
@swagger_auto_schema(
responses={
201: {
'schema': {
'description': 'Todo','required': ['username','tokens'],'type': 'object','properties': {
'username': {
'title': 'Username','type': 'string','maxLength': 64,'minLength': 1
},'email': {
'title': 'Email','readOnly': True,'maxLength': 254,'tokens': {
'$ref': '#/deFinitions/Tokens'
}
}
}
}
})
def post(self,request):
# ...
Failed to load API deFinition.
Errors
Fetch error
Internal Server Error http://localhost:8000/api/v0-alpha/?format=openapi
我能想到的唯一其他选择是为每个模式创建一个序列化程序,但这似乎比必要的更费力。有什么想法吗?
解决方法
您可以将嵌套序列化器的 Meta 类的 ref_name
设置为 None
,如下所述:
https://github.com/axnsan12/drf-yasg/issues/239#issuecomment-442629230