【问题标题】:Django swagger- How to disable DjangoFilterBackend query filters from delete, put methods?Django swagger-如何从删除、放置方法中禁用 DjangoFilterBackend 查询过滤器?
【发布时间】:2018-06-09 00:43:49
【问题描述】:

我创建了一个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) 中,但它们也出现在它们应该出现的 POSTPUTPATCHDELETE 中不会的。

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

【问题讨论】:

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


    【解决方案1】:

    如果您不想(每次)手动添加架构,那么解决方案如下: 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()
    

    【讨论】:

    • 谢谢,我才意识到我可以覆盖 MySchema 中的 _allows_filters()。
    【解决方案2】:

    没有必要为每个模型指定一个 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
    } 
    

    【讨论】:

      猜你喜欢
      • 2011-06-09
      • 2018-07-03
      • 2021-02-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-12
      • 1970-01-01
      相关资源
      最近更新 更多