Django swagger- How to disable DjangoFilterBackend query filters from delete, put methods?
Asked Answered
T

2

14

I've created an AssetsFilter class:

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 ']

Now I'm using this filter in my Viewset as follows:

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)

When the swagger documentation is created, the filter fields appear in GET (list), GET (retrieve) as expected, but they also appear in the POST, PUT, PATCH and DELETE where they shouldn't be.

How can I disable those parameters from appearing in the latest version of django-rest-swagger and DRF?

Tjader answered 28/12, 2017 at 12:59 Comment(0)
T
9

If you don't want to Add Schema Manually(Every time) then Here is the solution: 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()
Tjader answered 14/1, 2018 at 8:32 Comment(1)
Thx, i just realize that I can overwrite _allows_filters() in MySchema.Passion
D
1

Specifying a CustomSchema for every model is not necessary. It is possible to override the DjangoFilterBackend and prevent it from adding the schema fields for some specified actions:

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)

in settings.py :

REST_FRAMEWORK = {
    'DEFAULT_FILTER_BACKENDS': (
       'api.filter_backends.MyDjangoFilterBackend'
    ),
    'DEFAULT_PAGINATION_CLASS': 'api.pagination.MyPagination',
    'PAGE_SIZE': 20
} 
Distinguish answered 15/1, 2019 at 5:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.