Python 如何在 Django REST Framework 中显示查询参数选项 - Swagger
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/28203070/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to show query parameter options in Django REST Framework - Swagger
提问by dajee
This has been bugging me for a while now.
这已经困扰我一段时间了。
My ultimate goal is to show query parameter options inside SwaggerUI and give a form input for each query parameter. Similar to how it is displayed when providing a serializer for POST.
我的最终目标是在 SwaggerUI 中显示查询参数选项,并为每个查询参数提供一个表单输入。类似于为 POST 提供序列化程序时的显示方式。
I am using a viewset which inherits from GenericViewSet and I have tried the following:
我正在使用从 GenericViewSet 继承的视图集,我尝试了以下操作:
- provide
filter_fields
attribute - provide and set
filter_backends
attribute to(filters.DjangoFilterBackend,)
- provide filter_class defined inside my module.
- Override
options
method to provide[actions][GET]
information
- 提供
filter_fields
属性 - 提供并设置
filter_backends
属性(filters.DjangoFilterBackend,)
- 提供在我的模块中定义的 filter_class。
options
提供[actions][GET]
信息的覆盖方法
Here's a small catch, I am not using any models so I don't think DjangoFilterBackend will really help me. I am using DjangoRESTFramework to talk to an outside API, and I am simply getting JSON result back, and passing it through to the frontend layer.
这是一个小问题,我没有使用任何模型,所以我认为 DjangoFilterBackend 不会真正帮助我。我正在使用 DjangoRESTFramework 与外部 API 对话,我只是简单地获取 JSON 结果,并将其传递给前端层。
Here is a small modified snippet of my code to better explain my problem:
这是我的代码的一小段修改后的片段,以更好地解释我的问题:
views.py
视图.py
class SomeViewSet(GenericViewSet):
# Note that I have all of these defined, but I have tried various combinations
filter_fields = ('query_option_1', 'query_option_2',)
filter_backeds = (filters.DjangoFilterBackend,)
filter_class = SomeFilter
query_metadata = some_dict
# This works when request is OPTIONS
def options(self, request, *args, **kwargs):
if self.metadata_class is None:
return self.http_method_not_allowed(request, *args, **kwargs)
data = self.metadata_class().determine_metadata(request, self)
data['actions']['GET'] = self.query_metadata
return Response(data, status=status.HTTP_200_OK)
filters.py
过滤器.py
class SomeFilter(FilterSet):
strict = True
query_option_1 = django_filters.NumberFilter(name='query_option_1')
query_option_2 = django_filters.NumberFilter(name='query_option_2')
class Meta:
fields = ['query_option_1', 'query_option_2']
Thank you for looking, and thanks in advance for responding.
感谢您的关注,并提前感谢您的回复。
采纳答案by dajee
Okay, for those who stumble upon this question, I have figured it out. It is rather silly, and I feel a little stupid for not knowing, but in my defense, it was not clearly documented. The information was not found in DRF documentation, or inside Django REST Swagger repository. Instead it was found under django-rest-framework-docs, which is what Django REST Swagger is built off of.
好的,对于那些偶然发现这个问题的人,我已经弄清楚了。这是相当愚蠢的,我觉得不知道有点愚蠢,但在我的辩护中,它没有明确记录。在 DRF 文档或 Django REST Swagger 存储库中找不到该信息。相反,它是在 django-rest-framework-docs 下找到的,这是 Django REST Swagger 的构建基础。
To specify your query parameter to show up in your SwaggerUI as a form field, you simply comment like so:
要指定您的查询参数作为表单字段显示在 SwaggerUI 中,您只需像这样评论:
def list(self):
"""
param1 -- A first parameter
param2 -- A second parameter
"""
...
And swagger will parse your comments and will put a form input for param1 and param2. What follows --
are the descriptions for the parameters.
swagger 将解析您的评论,并为 param1 和 param2 输入表单。下面--
是对参数的说明。
回答by soooooot
I found the rest framework swagger docs. so we can write the parameter type(interger, char), response, etc.
我找到了其余框架 swagger docs。所以我们可以写参数类型(整数,字符),响应等。
the tripple ---
is necessary.
三元组---
是必要的。
@api_view(["POST"])
def foo_view(request):
"""
Your docs
---
# YAML (must be separated by `---`)
type:
name:
required: true
type: string
url:
required: false
type: url
created_at:
required: true
type: string
format: date-time
serializer: .serializers.FooSerializer
omit_serializer: false
parameters_strategy: merge
omit_parameters:
- path
parameters:
- name: name
description: Foobar long description goes here
required: true
type: string
paramType: form
- name: other_foo
paramType: query
- name: other_bar
paramType: query
- name: avatar
type: file
responseMessages:
- code: 401
message: Not authenticated
"""
How about the situation we use the mixins class such as ModelViewSets
.
Do we need to define the list
function just to add the docs?
-- No
我们使用 mixins 类的情况如何,例如ModelViewSets
. 我们是否需要定义list
函数来添加文档? - 不
We can do like this:
我们可以这样做:
class ArticleViewSet(viewsets.ModelViewSet):
"""
Articles.
---
list: #<--- here!!
parameters:
- name: name
description: article title
get_price:
omit_serializer: true
"""
@list_route(methods=['get'])
def get_price(self, request):
pass
回答by vadimchin
New swagger
新招摇
from rest_framework.filters import BaseFilterBackend
import coreapi
class SimpleFilterBackend(BaseFilterBackend):
def get_schema_fields(self, view):
return [coreapi.Field(
name='query',
location='query',
required=False,
type='string'
)]
class MyViewSet(viewsets.ViewSet):
filter_backends = (SimpleFilterBackend,)
def list(self, request, *args, **kwargs):
# print(request.GET.get('query')) # Use the query param in your view
return Response({'hello': 'world'}, status.HTTP_200_OK)
回答by Sean Chon
Disclaimer: I am using django_filters
, so results may vary. django_filters
uses the param filter_fields
in the DRF ViewSet, which may be different than not using django_filters
.
免责声明:我正在使用django_filters
,因此结果可能会有所不同。django_filters
使用filter_fields
DRF ViewSet 中的参数,这可能与不使用django_filters
.
I took inspiration from this threadand overrode the get_schema_fields()
method in the filtering backend in the following way.
我从这个线程中获得灵感,并get_schema_fields()
通过以下方式覆盖了过滤后端中的方法。
settings.py
设置.py
REST_FRAMEWORK = {
...
'DEFAULT_FILTER_BACKENDS': ('location.of.custom_backend.CustomDjangoFilterBackend')
...
}
custom_backend.py
custom_backend.py
import coreapi
import coreschema
from django_filters.rest_framework import DjangoFilterBackend
class CustomDjangoFilterBackend(DjangoFilterBackend):
"""
Overrides get_schema_fields() to show filter_fields in Swagger.
"""
def get_schema_fields(self, view):
assert (
coreapi is not None
), "coreapi must be installed to use `get_schema_fields()`"
assert (
coreschema is not None
), "coreschema must be installed to use `get_schema_fields()`"
# append filter fields to existing fields
fields = super().get_schema_fields(view)
if hasattr(view, "filter_fields"):
fields += view.filter_fields
return [
coreapi.Field(
name=field,
location='query',
required=False,
type='string',
) for field in fields
]
回答by Sean Chon
Elaborating on the answers above from @vadimchin - here is a working example.
详细说明@vadimchin 上面的答案 - 这是一个工作示例。
# requirements.txt
djangorestframework==3.9.3
django-rest-swagger==2.2.0
django==2.2.1
coreapi==2.3.3
I am using Viewsets in my application. I had to implement filter_queryset(self, request, queryset, view)
as suggested by @jarussi.
我在我的应用程序中使用视图集。我必须filter_queryset(self, request, queryset, view)
按照@jarussi 的建议实施。
# models.py
from django.db import models
class Recording(models.Model):
_id = models.AutoField(primary_key=True)
name = models.CharField(max_length=511)
# serializers.py
from models import Recording
from rest_framework import serializers
class RecordingSerializer(serializers.ModelSerializer):
class Meta:
model = Recording
fields = '__all__'
# views.py
from rest_framework import viewsets
from filters import NameFilterBackend
from serializers import RecordingSerializer
class RecordingViewSet(viewsets.ModelViewSet):
serializer_class = RecordingSerializer
queryset = Recording.objects.all()
filter_backends = (NameFilterBackend,)
# filters.py
from rest_framework.filters import BaseFilterBackend
import coreapi
class NameFilterBackend(BaseFilterBackend):
def get_schema_fields(self, view):
return [coreapi.Field(
name='name',
location='query',
required=False,
type='string',
description='name of recording'
)]
def filter_queryset(self, request, queryset, view):
try:
n = request.query_params['name']
queryset = queryset.filter(name=n)
except KeyError:
# no query parameters
pass
return queryset
回答by Devaroop
Please refer this github issuewhich solves the problem.
请参考解决问题的这个 github问题。
回答by NiKo
Working with openapi (and not coreapi), the "simplest" way I found is from this core dev comment:
使用 openapi(而不是 coreapi),我发现的“最简单”的方法来自这个核心开发评论:
from rest_framework.schemas.openapi import AutoSchema
class CustomSchema(AutoSchema):
def get_operation(self, path, method):
op = super().get_operation(path, method)
op['parameters'].append({
"name": "foo",
"in": "query",
"required": True,
"description": "What foo does...",
'schema': {'type': 'string'}
})
return op
class MyViewSet(ModelViewSet):
schema = CustomSchema()
def get_queryset(self):
foo = self.request.query_params.get("foo")
if foo:
self.queryset = self.queryset.filter(foo=foo)
return self.queryset