【问题标题】:Django REST Framework - How to disable the browsable API for non staff users (is_staff=False)Django REST Framework - 如何禁用非员工用户的可浏览 API (is_staff=False)
【发布时间】:2020-03-12 01:18:44
【问题描述】:

在我的例子中,我使用 Django REST Framework (DRF) 作为内部 api。它不适合普通用户使用。因此我想为普通用户禁用它。

管理员 (is_staff=True) 应该能够访问并看到它:
https://restframework.herokuapp.com/

非员工用户 (is_staff=False) 应该只获得 GET 请求的 JSON 响应,例如:
https://restframework.herokuapp.com/?format=json 他应该不(!)看到可浏览的 api。这适用于根视图和所有端点。

为了配置它,我应用了以下内容:

# settings.py

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': ['rest_framework.authentication.SessionAuthentication'],
    'DEFAULT_PERMISSION_CLASSES': ['rest_framework.permissions.IsAuthenticated'],
}

我的端点如下(为了保持示例简单,我只显示 1):

# api/urls.py
from django.urls import include, path

from rest_framework import routers

from . import views

app_name = 'api'

router = routers.DefaultRouter()  # browseable api
router.register('segments', views.SegmentViewSet)
# there are a lot more...

urlpatterns = [
    path('', include(router.urls)),
]

基于答案https://stackoverflow.com/a/58894198/420953 我的settings.py 看起来像这样:

# settings.py

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': ['rest_framework.authentication.SessionAuthentication'],
    'DEFAULT_PERMISSION_CLASSES': ['rest_framework.permissions.IsAuthenticated'],
    # enable JSON renderer by default
    'DEFAULT_RENDERER_CLASSES': [
        'rest_framework.renderers.JSONRenderer',
    ],
}

还有我的api/views.py

# api/views.py

from django_filters import rest_framework as drf_filters
from rest_framework import filters, renderers, viewsets

from . import serializers
from segment.models import Segment

class StaffBrowsableAPIMixin:
    def get_renderers(self):
        """
        add BrowsableAPIRenderer if user is staff (regular users see JSONRenderer response)
        """
        # explicitly set renderer to JSONRenderer (the default for non staff users)
        rends = [renderers.JSONRenderer]
        if self.request.user.is_staff:
            # staff users see browsable API
            rends.append(renderers.BrowsableAPIRenderer)
        return [renderer() for renderer in rends]

class SegmentViewSet(StaffBrowsableAPIMixin, viewsets.ReadOnlyModelViewSet):
    queryset = Segment.objects.all()
    serializer_class = serializers.SegmentSerializer

这适用于所有端点(当普通用户通过 GET 调用端点时,他们只能看到 JSON,而不是可浏览的 API)。不幸的是,它不适用于APIRootView(api 的根视图,例如https://restframework.herokuapp.com/)。

如何让它也适用于APIRootView

【问题讨论】:

  • 你得到了什么结果?
  • 能否请您检查您正在登录的用户是否将属性 is_staff 设置为 true 或 false?
  • 谢谢你!正是我想要的。错过了这篇文章。
  • 乐于助人:)

标签: python django django-rest-framework


【解决方案1】:

编辑

更好地了解您的问题(我相信),您可以非常简单地锁定 API 的基本 URL(mixin 可能应该移动到另一个文件,但为了清晰起见,只需将所有内容放在一起):

# api/urls.py
from django.urls import include, path

from rest_framework import permissions, renderers, routers

from . import views

app_name = 'api'

class StaffBrowsableAPIMixin:
    def get_renderers(self):
        """
        add BrowsableAPIRenderer if user is staff (regular users see JSONRenderer response)
        """
        # explicitly set renderer to JSONRenderer (the default for non staff users)
        rends = [renderers.JSONRenderer]
        if self.request.user.is_staff:
            # staff users see browsable API
            rends.append(renderers.BrowsableAPIRenderer)
        return [renderer() for renderer in rends]


class CustomAPIRootView(StaffBrowsableAPIMixin, routers.APIRootView):
    permission_classes = (permissions.IsAdminUser,)


class CustomDefaultRouter(routers.DefaultRouter):
    APIRootView = CustomAPIRootView

router = CustomDefaultRouter()  # browseable api
router.register('segments', views.SegmentViewSet)
# there are a lot more...

urlpatterns = [
    path('', include(router.urls)),
]

permission_classes 将处理不向非管理员用户显示您的任何端点,但仍会显示可浏览 API 模板。要同时删除它,您需要使用 StaffBrowsableAPIMixin 更改渲染器。


原答案

一种方法是使用 DRF 的渲染器设置和方法。

在你的settings.py

REST_FRAMEWORK = {
    # Only enable JSON renderer by default.
    'DEFAULT_RENDERER_CLASSES': [
        'rest_framework.renderers.JSONRenderer',
    ],
}

在你的views.py:

from rest_framework import generics, renderers

class StaffBrowsableMixin(object):
    def get_renderers(self):
        """
        Add Browsable API renderer if user is staff.
        """
        rends = self.renderer_classes
        if self.request.user and self.request.user.is_staff:
            rends.append(renderers.BrowsableAPIRenderer)
        return [renderer() for renderer in rends]

class CustomListApiView(StaffBrowsableMixin, generics.ListAPIView):
    """
    List view.
    """
    # normal stuff here

基本上,将StaffBrowsableMixin 用于您希望为员工启用 BrowsableAPI 的任何APIView

类似的问题,如上面在 cmets 中的链接,以及我的回答:https://stackoverflow.com/a/58762483/4599228

【讨论】:

  • 你也知道如何将它应用到 APIRootView 吗?
  • @udo 您能否更新您的问题以包括您的urls.py 以及您如何尝试使用您在上面写的自定义APIRootView?然后我可以更新我的答案以(希望)满足您的需求。
  • 我重新表述了这个问题。希望现在更清楚了。
  • :) 关于您上次编辑的错误理解。不用担心。澄清:所有(!)用户都有权访问 API。它只是可浏览的 API,必须仅限于员工用户。
  • @udo 是的,在发布后被评论删除后才意识到 :) 我重新编辑,检查一下,让我知道这是否有效。
猜你喜欢
  • 2015-10-09
  • 1970-01-01
  • 2022-10-03
  • 2013-09-20
  • 2016-03-24
  • 2021-11-02
  • 2014-05-28
  • 2015-01-16
  • 1970-01-01
相关资源
最近更新 更多