Как показать параметры параметров запроса в Django REST Framework - Swagger
Это уже некоторое время подтачивало меня.
Моя конечная цель - показать параметры параметров запроса внутри SwaggerUI и предоставить ввод формы для каждого параметра запроса. Аналогично тому, как он отображается при предоставлении сериализатора для POST.
Я использую viewet, который наследует от GenericViewSet, и я пробовал следующее:
- укажите атрибут
filter_fields
- укажите и установите атрибут
filter_backends
на (filters.DjangoFilterBackend,)
- предоставить filter_class, определенный внутри моего модуля.
- Переопределить метод
options
для предоставления [actions][GET]
информации
Вот небольшой улов, я не использую никаких моделей, поэтому я не думаю, что DjangoFilterBackend действительно поможет мне. Я использую DjangoRESTFramework, чтобы поговорить с внешним API, и я просто возвращаю результат JSON и передаю его интерфейсу.
Вот небольшой модифицированный фрагмент кода, чтобы лучше объяснить мою проблему:
views.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
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']
Спасибо, что посмотрели, и спасибо заранее за ответ.
Ответы
Ответ 1
Хорошо, для тех, кто наткнулся на этот вопрос, я понял это. Это довольно глупо, и я чувствую себя немного глупо за то, что не знаю, но в свою защиту он не был четко документирован. Информация не была найдена в документации DRF или в репозитории Django REST Swagger. Вместо этого он был найден в django-rest-framework-docs, из-за чего построен Django REST Swagger.
Чтобы указать ваш параметр запроса для отображения в вашем SwaggerUI в качестве поля формы, вы просто прокомментируете так:
def list(self):
"""
param1 -- A first parameter
param2 -- A second parameter
"""
...
И swagger будет анализировать ваши комментарии и будет вводить ввод формы для param1 и param2. Ниже следует --
описание параметров.
Ответ 2
Новый чванство
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)
Ответ 3
Я нашел dag docs.
поэтому мы можем написать тип параметра (interger, char), ответ и т.д.
необходим триплекс ---
.
@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
"""
Как насчет ситуации, в которой мы используем класс mixins, например ModelViewSets
.
Нужно ли нам определять функцию list
только для добавления документов?
- Нет
Мы можем сделать вот так:
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
Ответ 4
Отказ от ответственности: я использую django_filters
, поэтому результаты могут отличаться. django_filters
использует параметры param filter_fields
в DRF ViewSet, которые могут отличаться от использования django_filters
.
Я черпал вдохновение из этого потока и get_schema_fields()
метод get_schema_fields()
в фильтрующем get_schema_fields()
следующим образом.
settings.py
REST_FRAMEWORK = {
...
'DEFAULT_FILTER_BACKENDS': ('location.of.custom_backend.CustomDjangoFilterBackend')
...
}
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
]
Ответ 5
Разрабатывая ответы выше от @vadimchin - вот рабочий пример.
# requirements.txt
djangorestframework==3.9.3
django-rest-swagger==2.2.0
django==2.2.1
coreapi==2.3.3
Я использую Viewsets в моем приложении. Мне пришлось реализовать 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
Ответ 6
Пожалуйста, обратитесь к этой проблеме GitHub, которая решает проблему.