【问题标题】:Why is DRF browsable API running permission checks on multiple request types for every actual request?为什么 DRF 可浏览 API 对每个实际请求的多个请求类型运行权限检查?
【发布时间】:2018-10-09 22:26:22
【问题描述】:

我有一个简单的 DRF 列表视图,想写一些与 POST 请求有关的权限。这导致在发出GET 请求时出错。这让我意识到我的权限类在未提交的请求上被多次调用。这是我的文件。

permissons.py:

class IsDummy(permissions.BasePermission):
    def has_permission(self, request, view):
        print("\n{}\n".format(request.method)) 
        if request.method in permissions.SAFE_METHODS:
            return True
        return False

views.py:

class UserListView(generics.ListCreateAPIView):
    queryset = User.objects.all()
    serializer_class = UserSerializer
    permission_classes = [IsDummy]

仅当我在可浏览 api 上从浏览器提交请求时才会出现此问题。当我在列表 url 提交 GET 请求时,我会从IsDummy 权限类中的打印语句将以下内容打印到终端:

GET

POST

POST

OPTIONS

当我通过邮递员提交GETOPTIONS 请求时,我看到了我实际使用的单一、适当的请求方法。

似乎列出的第一个方法总是我使用的实际方法,我不知道额外的POSTs 和OPTION 是从哪里来的。更奇怪的是,尽管POST 请求显然应该导致IsDummy.has_permission 返回False,但页面将在所有这些之后正常加载。

chrome 开发工具仅显示提交了一个 GET 请求,因为它似乎只发生在可浏览的 api 中,我确信它与此有关,但我无法弄清楚我搞砸了什么为实现这一目标而努力。

【问题讨论】:

  • browser api是一个可以添加\更新\删除实例的signle页面,当你询问这个页面时,drf会检查所有需要的权限,看看相应的模块是否需要显示

标签: python django django-rest-framework


【解决方案1】:

浏览器 API 是一个可以添加\更新\删除实例的单一页面。当您询问此页面时,DRF 会检查所有必需的权限,以查看是否允许显示相应的模块。

深入DRF源代码,可以在renderers.py看到这个:

class BrowsableAPIRenderer(BaseRenderer):
    """
    HTML renderer used to self-document the API.
    """
    media_type = 'text/html'
    format = 'api'
    template = 'rest_framework/api.html'
    filter_template = 'rest_framework/filters/base.html'
    code_style = 'emacs'
    charset = 'utf-8'
    form_renderer_class = HTMLFormRenderer

    ...

    def get_context(self, data, accepted_media_type, renderer_context):
         ....
         context = {
             ....
            'put_form': self.get_rendered_html_form(data, view, 'PUT', request),
            'post_form': self.get_rendered_html_form(data, view, 'POST', request),
            'delete_form': self.get_rendered_html_form(data, view, 'DELETE', request),
            'options_form': self.get_rendered_html_form(data, view, 'OPTIONS', request),
         }
         return context

    def get_rendered_html_form(self, data, view, method, request):
        ....
        if not self.show_form_for_method(view, method, request, instance):
            ....

    def show_form_for_method(self, view, method, request, obj):
        """
        Returns True if a form should be shown for this method.
        """
        if method not in view.allowed_methods:
            return  # Not a valid method

        try:
            view.check_permissions(request)
            if obj is not None:
                view.check_object_permissions(request, obj)
        except exceptions.APIException:
            return False  # Doesn't have permissions
        return True

show_form_for_method 中的view.check_permissions(request) 是 DRF 可浏览 API 对每个实际请求的多种请求类型运行权限检查的原因。

【讨论】:

  • 不错的发现 :) DRF 对 API 请求有相同的行为吗?
  • 否,api 请求只检查所需的权限请求 url。
  • 谢谢,正是我想要的。检查方法是否是不好的做法,例如POST,在权限类中?没有更多地讨论这似乎很奇怪。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多