我正在浏览django REST框架教程,除了用我自己的自定义用户模型替换Snippet模型。但是,当我尝试测试API时,我会继续
Traceback (most recent call last):
File "/Users/AndyFang/Desktop/doorstep-django/venv/lib/python2.7/site-packages/django/core/handlers/base.py", line 115, in get_response
response = callback(request, *callback_args, **callback_kwargs)
File "/Users/AndyFang/Desktop/doorstep-django/venv/lib/python2.7/site-packages/django/views/generic/base.py", line 68, in view
return self.dispatch(request, *args, **kwargs)
File "/Users/AndyFang/Desktop/doorstep-django/venv/lib/python2.7/site-packages/django/views/decorators/csrf.py", line 77, in wrapped_view
return view_func(*args, **kwargs)
File "/Users/AndyFang/Desktop/doorstep-django/venv/lib/python2.7/site-packages/rest_framework/views.py", line 326, in dispatch
response = self.handle_exception(exc)
File "/Users/AndyFang/Desktop/doorstep-django/venv/lib/python2.7/site-packages/rest_framework/views.py", line 314, in dispatch
self.initial(request, *args, **kwargs)
File "/Users/AndyFang/Desktop/doorstep-django/venv/lib/python2.7/site-packages/rest_framework/views.py", line 235, in initial
self.check_permissions(request)
File "/Users/AndyFang/Desktop/doorstep-django/venv/lib/python2.7/site-packages/rest_framework/views.py", line 192, in check_permissions
if not permission.has_permission(request, self):
File "/Users/AndyFang/Desktop/doorstep-django/venv/lib/python2.7/site-packages/rest_framework/permissions.py", line 131, in has_permission
if model_cls is None and getattr(view, '_ignore_model_permissions'):
AttributeError: 'user_list' object has no attribute '_ignore_model_permissions'
我已经尝试了各种方法来解决这个问题(例如禁用格式功能,添加csrf_exmept令牌等)都无济于事。以下是我写的代码:
serializers.py
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('id', 'email', 'phone_number', 'first_name', 'last_name')
views.py
@api_view(['GET', 'POST'])
def user_list(request, format=None):
"""
List all users, or create a new user.
"""
if request.method == 'GET':
users = User.objects.all()
serializer = UserSerializer(users, many=True)
return Response(serializer.data)
elif request.method == 'POST':
serializer = UserSerializer(data=request.DATA)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
else:
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
@api_view(['GET', 'PUT', 'DELETE'])
def user_detail(request, pk, format=None):
"""
Retrieve, update or delete a user instance.
"""
try:
user = User.objects.get(pk=pk)
except User.DoesNotExist:
return Response(status=status.HTTP_404_NOT_FOUND)
if request.method == 'GET':
serializer = UserSerializer(user)
return Response(serializer.data)
elif request.method == 'PUT':
serializer = UserSerializer(user, data=request.DATA)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
else:
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
elif request.method == 'DELETE':
user.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
urls.py
答案 0 :(得分:8)
那里有一点bug,不应该在那里引发AttributeError - 我现在刚刚在master中修复了它。
相反,当你对master运行时你会看到的是这个断言错误:
Cannot apply DjangoModelPermissions on a view that does not have `.model` or `.queryset` property.
这里的问题是DjangoModelPermissions
类只有在确定视图需要哪些模型权限时才能工作。如果要使用该权限类,则需要将视图重写为基于类的视图,并确保它们已正确设置model
属性。
请注意,仅仅因为您将它们重写为基于类的视图并不意味着您需要使用基于泛型类的视图,您仍然可以保留当前具有的显式视图逻辑。像这样:
class UserListView(views.APIView):
queryset = User.objects.all()
def get(self, request, format=None):
users = self.queryset
serializer = UserSerializer(users, many=True)
return Response(serializer.data)
def post(self, request, format=None):
serializer = UserSerializer(data=request.DATA)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
else:
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
class UserDetailView(views.APIView):
queryset = User.objects.all()
def get_object(self, pk)
try:
return self.queryset.get(pk=pk)
except User.DoesNotExist:
raise Http404
def get(self, request, pk, format=None):
user = self.get_object(pk)
serializer = UserSerializer(user)
return Response(serializer.data)
def put(self, request, pk, format=None):
user = self.get_object(pk)
serializer = UserSerializer(user, data=request.DATA)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
else:
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def delete(self, request, pk, format=None):
user = self.get_object(pk)
user.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
请注意,在这两种情况下使用queryset
表示现在可以将DjangoModelPermissions
应用于这些视图。
答案 1 :(得分:5)
您可能在设置中将DjangoModelPermissions
或类似设置为默认权限类。类似的东西:
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly',
)
}
默认情况下,这将检查用户是否对视图所基于的模型具有权限。如果您查看没有设置模型,则无法找到权限。所以你需要在视图上设置模型。据我所知,这只能在基于类的APIView中看到:
from .models import MyModel
class MyView(APIView):
model = MyModel
def get(self, request, pk):
# ...
如果您的视图不是基于Django模型,您可以从REST_FRAMEWORK
设置中删除此默认类,也可以在视图上设置自定义权限类,例如:
from rest_framework import permissions
class MyView(APIView)
permission_classes = (permissions.IsAuthenticated,)
def get(self, request, pk):
# ...
或者在基于功能的视图中:
from rest_framework import permissions
@api_view(['GET', 'POST'])
@permission_classes((permissions.IsAuthenticated,))
def my_view(request)
# ...
有关权限的详情,请参阅http://django-rest-framework.org/api-guide/permissions.html
答案 2 :(得分:2)
这是最简单的:
@api_view(['POST'])
@permission_classes((permissions.AllowAny,))
def my_view(request)
# ...
答案 3 :(得分:0)
目前正在做其余的框架教程,而不是重写我的视图,因为我很新手我只是将我的settings.py中的权限设置更改为下面的框架,所有看起来都很好,因为我是不再从模型中获取权限。
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated',
]