Django swagger-如何从delete,put方法中禁用DjangoFilterBackend查询过滤器?

时间:2017-12-28 12:59:38

标签: python django django-rest-framework swagger django-rest-swagger

我创建了一个AssetsFilter类:

from django_filters import Filter
from django_filters import rest_framework as filters
from django_filters.fields import Lookup

from .models import Assets


class MyListFilter(Filter):
    def filter(self, qs, value):
        value_list = value.split(',')
        return super(ListFilter, self).filter(qs, Lookup(value_list, 'in'))


class AssetsFilter(filters.FilterSet):
    name = filters.CharFilter(lookup_expr='icontains', help_text=u'Filter by name')
    criticality = MyListFilter(name='critical', help_text=u'Filter by_id')

    class Meta:
        model = Assets
        fields = ['name', 'criticality ']

现在我在我的Viewset中使用此过滤器,如下所示:

from .serializers import AssetSerializers
from .filters import AssetsFilter


class AssetViewSet(viewsets.ModelViewSet):
    """
    This viewset automatically provides `list`, `create`, `retrieve`,
    `update` and `destroy` actions.
    """
    queryset = Assets.objects.all()
    serializer_class = AssetSerializers
    filter_backends = (DjangoFilterBackend,)
    filter_class = AssetsFilter
    http_method_names = ['get', 'post', 'put', 'delete']

    def list(self, request):
        """
        Returns a list of Asset.
        """
        return super(AssetViewSet, self).list(request)

    def create(self, request):
        """
        Creates a new Asset.<br>
        """
        return super(AssetViewSet, self).create(request)

    def destroy(self, request, pk=None):
        """
        Deletes a Asset.
        """
        return super(AssetViewSet, self).destroy(request, pk=pk)

    def retrieve(self, request, pk=None):
        """
        Returns a Asset with id={id}
        """
        return super(AssetViewSet, self).retrieve(request, pk=pk)

    def update(self, request, pk=None, *args, **kwargs):
        """
        Updates an existing Asset.<br>
        """
        return super(AssetViewSet, self).update(request, pk=pk, *args, **kwargs)

创建swagger文档后,过滤器字段会按预期显示在GET (list)GET (retrieve)中,但它们也会显示在POSTPUT,{{1 }}和PATCH他们不应该在那里。

如何禁用这些参数出现在最新版本的django-rest-swagger和DRF中?

2 个答案:

答案 0 :(得分:7)

如果您不想手动添加架构(每次),那么以下是解决方案: auto_schema.py

from rest_framework.schemas import AutoSchema
from django.utils.six.moves.urllib import parse as urlparse
import coreapi, coreschema


class CustomSchema(AutoSchema):
    def get_link(self, path, method, base_url):
        fields = self.get_path_fields(path, method)
        fields += self.get_serializer_fields(path, method)
        fields += self.get_pagination_fields(path, method)
        if self.view.action in ['list']:
            fields += self.get_filter_fields(path, method)

        manual_fields = self.get_manual_fields(path, method)
        fields = self.update_fields(fields, manual_fields)

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

        description = self.get_description(path, method)

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

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

views.py

class MyUserViewSet(viewsets.ModelViewSet):
    """
    API endpoint that allows users to be viewed or edited.

    """
    model = MyUser
    serializer_class = MyUserSerializer
    queryset = MyUser.objects.all()
    filter_backends = (DjangoFilterBackend, OrderingFilter)
    filter_class = MyUserFilter
    ordering_fields = ('last_name', 'first_name', 'email', 'is_active')
    ordering = ('last_name', 'first_name')
    permission_classes = (IsAuthenticated,)
    schema = CustomSchema()

答案 1 :(得分:0)

不必为每个模型都指定一个CustomSchema。 可以覆盖DjangoFilterBackend并阻止它为某些指定的操作添加架构字段:

class MyDjangoFilterBackend(DjangoFilterBackend):
    def get_schema_fields(self, view):
        # Customize according to your need here.
        if view.action not in ["list"]:
            return []
        return super().get_schema_fields(view)

在settings.py中:

REST_FRAMEWORK = {
    'DEFAULT_FILTER_BACKENDS': (
       'api.filter_backends.MyDjangoFilterBackend'
    ),
    'DEFAULT_PAGINATION_CLASS': 'api.pagination.MyPagination',
    'PAGE_SIZE': 20
}