has_permission()缺少1个必需的位置参数:'view'

时间:2016-05-08 08:41:50

标签: python django django-rest-framework

我正在开发一个用于学习目的的项目,具有以下配置: Python 3.4.4 Django的== 1.9.1 djangorestframework == 3.3.3 操作系统(Windows 8.1)`

在项目中我有一个模型Post,我创建了permissions.py

from rest_framework import permissions


class IsAuthorOfPost(permissions.BasePermission):
    def has_permission(self, request, view):
        return True

    def has_object_permission(self, request, view, post):
        if request.user:
            return post.author == request.user
        return False
  

views.py:

from rest_framework import permissions, viewsets
from rest_framework.response import Response

from posts.models import Post
from posts.permissions import IsAuthorOfPost
from posts.serializers import PostSerializer


class PostViewSet(viewsets.ModelViewSet):
    queryset = Post.objects.order_by('-created_at')
    serializer_class = PostSerializer

    def get_permissions(self):
        if self.request.method in permissions.SAFE_METHODS:
            return (permissions.AllowAny(),)
        return (permissions.IsAuthenticated, IsAuthorOfPost(),)

    def perform_create(self, serializer):
        instance = serializer.save(author=self.request.user)
        return super(PostViewSet, self).perform_create(serializer)


class AccountPostViewSet(viewsets.ModelViewSet):
    queryset = Post.objects.select_related('author').all()
    serializer_class = PostSerializer

    def list(self, request, account_username=None):
        queryset = self.queryset.filter(author__username=account_username)
        serializer = self.serializer_class(queryset, many=True)

        return Response(serializer.data)
  

serializers.py:

from rest_framework import serializers

from authentication.serializers import AccountSerializer
from posts.models import Post


class PostSerializer(serializers.ModelSerializer):
    author = AccountSerializer(read_only=True, required=False)

    class Meta:
        model = Post
        fields = ('id', 'author', 'content', 'created_at', 'updated_at')
        read_only_fields = ('id', 'created_at', 'updated_at')

    def get_validation_exclusions(self, *args, **kwargs):
        exclusions = super(PostSerializer, self).get_validation_exclusions()

        return exclusions + ['author']
  

urls.py

from django.conf.urls import url, include
from django.contrib import admin
from rest_framework.routers import DefaultRouter
from rest_framework_nested import routers

from djangular.views import IndexView
from authentication.views import AccountViewSet, LoginView, LogoutView
from posts.views import PostViewSet, AccountPostViewSet

router = routers.SimpleRouter()

router.register(r'accounts', AccountViewSet)
router.register(r'posts', PostViewSet)

account_router = routers.NestedSimpleRouter(
    router, r'accounts', lookup='account'
)

account_router.register(r'posts', AccountPostViewSet)
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^api/v1/', include(router.urls)),
    url(r'^api/v1/', include(account_router.urls)),
    url(r'^api/v1/auth/login/$', LoginView.as_view(), name='login'),
    url(r'^api/v1/auth/logout/$', LogoutView.as_view(), name='logout'),
    url('^.*$', IndexView.as_view(), name='index'),
]

localhost:8000/api/v1/posts/

  

错误

TypeError at /api/v1/posts/
has_permission() missing 1 required positional argument: 'view'
Request Method: GET
Request URL:    http://localhost:8000/api/v1/posts/
Django Version: 1.9.1
Exception Type: TypeError
Exception Value:    
has_permission() missing 1 required positional argument: 'view'
Exception Location: C:\Users\Devansh\Envs\19\lib\site-packages\rest_framework\views.py in check_permissions, line 318
Python Executable:  C:\Users\Devansh\Envs\19\Scripts\python.exe
Python Version: 3.4.4
Python Path:    
['D:\\djangular-app',
 'C:\\Windows\\SYSTEM32\\python34.zip',
 'C:\\Users\\Devansh\\Envs\\19\\DLLs',
 'C:\\Users\\Devansh\\Envs\\19\\lib',
 'C:\\Users\\Devansh\\Envs\\19\\Scripts',
 'c:\\python34\\Lib',
 'c:\\python34\\DLLs',
 'C:\\Users\\Devansh\\Envs\\19',
 'C:\\Users\\Devansh\\Envs\\19\\lib\\site-packages']
  

回溯

Traceback (most recent call last):
  File "C:\Users\Devansh\Envs\19\lib\site-packages\django\core\handlers\ba
, line 174, in get_response
    response = self.process_exception_by_middleware(e, request)
  File "C:\Users\Devansh\Envs\19\lib\site-packages\django\core\handlers\ba
, line 172, in get_response
    response = response.render()
  File "C:\Users\Devansh\Envs\19\lib\site-packages\django\template\respons
 line 160, in render
    self.content = self.rendered_content
  File "C:\Users\Devansh\Envs\19\lib\site-packages\rest_framework\response
line 71, in rendered_content
    ret = renderer.render(self.data, media_type, context)
  File "C:\Users\Devansh\Envs\19\lib\site-packages\rest_framework\renderer
 line 676, in render
    context = self.get_context(data, accepted_media_type, renderer_context
  File "C:\Users\Devansh\Envs\19\lib\site-packages\rest_framework\renderer
 line 618, in get_context
    raw_data_post_form = self.get_raw_data_form(data, view, 'POST', reques
  File "C:\Users\Devansh\Envs\19\lib\site-packages\rest_framework\renderer
 line 521, in get_raw_data_form
    if not self.show_form_for_method(view, method, request, instance):
  File "C:\Users\Devansh\Envs\19\lib\site-packages\rest_framework\renderer
 line 417, in show_form_for_method
    view.check_permissions(request)
  File "C:\Users\Devansh\Envs\19\lib\site-packages\rest_framework\views.py
e 318, in check_permissions
    if not permission.has_permission(request, self):
TypeError: has_permission() missing 1 required positional argument: 'view'

1 个答案:

答案 0 :(得分:8)

您缺少permissions.IsAuthenticated的类实例化:

def get_permissions(self):
     if self.request.method in permissions.SAFE_METHODS:
         return (permissions.AllowAny(),)
     return (permissions.IsAuthenticated, IsAuthorOfPost(),)
#                                      ^^^

错误消息来自于调用类IsAuthenticated上的实例方法。因此request映射到selfview映射到request,然后view本身就会丢失。

get_permissions()更改为

def get_permissions(self):
     if self.request.method in permissions.SAFE_METHODS:
         return (permissions.AllowAny(),)
     return (permissions.IsAuthenticated(), IsAuthorOfPost(),)
#                                       ^^

应该解决问题。

作为旁注:您的get_permissions()代码在决定授权时发挥了积极作用。最好将此功能转移到权限本身,以使代码更好地遵循单一责任原则。