Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

has_permission() missing 1 required positional argument: 'view'

i am working on a project for learning purpose with following config: Python 3.4.4 django==1.9.1 djangorestframework==3.3.3 OS (Windows 8.1)`

In project i having a model Post for that i have created 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/

Error:

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

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'
like image 795
Devansh Avatar asked May 08 '16 08:05

Devansh


1 Answers

You are missing a class instantiation for permissions.IsAuthenticated:

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

The error message comes from calling the instance method on IsAuthenticated on the class. Thus request gets mapped to self, view to request and view itself is then missing.

Changing get_permissions() to

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

should solve the problem.

As a side note: Your get_permissions() code takes an active role in deciding authorization. It would be better to move this functionality into the permissions themselves to make the code better follow the single responsibility principle.

like image 52
dhke Avatar answered Oct 13 '22 06:10

dhke