9

我正在阅读 django REST 框架教程,除了用我自己的自定义 User 模型替换 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 令牌等),但均无济于事。下面是我写的代码:

序列化程序.py

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ('id', 'email', 'phone_number', 'first_name', 'last_name')

视图.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)

网址.py

4

4 回答 4

8

那是一个错误,不应该在那里引发 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现在将能够应用于这些视图。

于 2013-06-18T10:22:04.480 回答
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

于 2013-07-31T12:48:15.207 回答
2

这是最简单的:

 @api_view(['POST'])
 @permission_classes((permissions.AllowAny,))
 def my_view(request)
 # ...
于 2014-03-14T12:50:43.853 回答
0

目前也在做其余的框架教程,而不是因为我很新手而重写我的视图,我只是将框架的 settings.py 中的权限设置更改为以下内容,一切似乎都很好,因为我不再使用来自模型的权限。

'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.IsAuthenticated',
    ]
于 2013-12-29T03:43:38.807 回答