我正在开发一个用于学习目的的项目,具有以下配置: 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'),
]
错误:
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'
答案 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
映射到self
,view
映射到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()
代码在决定授权时发挥了积极作用。最好将此功能转移到权限本身,以使代码更好地遵循单一责任原则。