Django REST Framework-如何为非员工用户禁用可浏览的API(is_staff = False) [英] Django REST Framework - How to disable the browsable API for non staff users (is_staff=False)
问题描述
在我的情况下,我使用Django REST Framework(DRF)作为内部api。不适合普通用户使用。因此,我想对普通用户禁用它。
in my case I am using Django REST Framework (DRF) as internal api. it is not intended to be consumed by regular users. therefore I would like to disable it for regular users.
管理员( is_staff = True
)应该能够访问并查看它:
an admin (is_staff=True
) should be able to access it and see it:
https://restframework.herokuapp.com/
非工作人员用户( is_staff = False
)应该只获取GET请求的JSON响应,例如:
https ://restframework.herokuapp.com/?format = json
< img src = https://i.stack.imgur.com/vca9P.png alt =在此处输入图片描述>
他应该不(!)请参阅可浏览的api。这适用于根视图和所有端点。
a non staff user (is_staff=False
) should just get the JSON response of a GET request like:
https://restframework.herokuapp.com/?format=json
he should not(!) see the browsable api. this applies for the root view and all endpoints.
要进行配置,我应用了以下内容:
to configure this, I applied the following:
# settings.py
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': ['rest_framework.authentication.SessionAuthentication'],
'DEFAULT_PERMISSION_CLASSES': ['rest_framework.permissions.IsAuthenticated'],
}
我的端点如下(为了使示例简单,我只显示1):
my endpoints are the following (to keep the example simple I just show 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
看起来像这样:
based on answer https://stackoverflow.com/a/58894198/420953 my settings.py
looks like this:
# 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 /视图。 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/ )。
this works fine for all endpoints (when a regular user calls the endpoint via GET, they only see the JSON, not the browsable API). Unfortunately it does not work for APIRootView
(the root view of the api, e.g. https://restframework.herokuapp.com/).
如何在 APIRootView $中使用它c $ c>也是如此?
推荐答案
编辑
了解您的问题更好(我相信),您可以将API的基本URL锁定很简单(mixin可能应该移至另一个文件,但是为了清楚起见,只需将所有内容放在一起):
Edit
Understanding your problem better (I believe), you can lock the base URL of your API down pretty simply (the mixin should probably be moved to another file but just kept everything together for clarity):
# 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
将不会向非管理员用户显示任何终结点,但仍会显示Browsable API模板。要同时删除它,您需要使用 StaffBrowsableAPIMixin
更改渲染器。
The permission_classes
will handle not showing any of your endpoints to non-Admin users but the Browsable API template will still be shown. To remove that as well, you need to change the renderer using the StaffBrowsableAPIMixin
.
一种方法是使用DRF的渲染器设置和方法。
One way to do this is using DRF's renderer settings and methods.
在您的 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
,对于希望为st启用BrowsableAPI的任何 APIView
使用 StaffBrowsableMixin
Basically, use StaffBrowsableMixin
for any APIView
you want the BrowsableAPI to be enabled for staff.
类似的问题,如上面评论中的链接以及我在那的答案: https://stackoverflow.com/a/58762483/4599228
Similar question, as linked above in comments, and my answer there as well: https://stackoverflow.com/a/58762483/4599228
这篇关于Django REST Framework-如何为非员工用户禁用可浏览的API(is_staff = False)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!