在 Django Tastypie 中将用户 API 响应限制为当前用户

75 阅读2分钟

在使用 Django Tastypie 创建简单的 API 时,我遇到了一个问题。我使用了自定义的身份验证(实际上并不算太自定义,因为它直接从他们的示例中复制而来),它只显示当前用户的数据。然而,它却返回了所有用户,而我只想显示已登录的用户。

以下是我当前使用的 api.py 代码:

class UserResource(ModelResource):
    class Meta:
        queryset = User.objects.all()
        excludes = ['password', 'is_superuser']
        resource_name = 'user'
       authentication=MultiAuthentication(SessionAuthentication(),ApiKeyAuthentication())
        authorization=DjangoAuthorization()
        allow_methods=['get']

class EntryResource(ModelResource):
    user = fields.ForeignKey(UserResource, 'user')
    class Meta:
        queryset = Entry.objects.all()
        resource_name = 'entry'
        authentication=MultiAuthentication(SessionAuthentication(),ApiKeyAuthentication())
        authorization=UserObjectsOnlyAuthorization()

对于 UserObjectsOnlyAuthorization,我使用了以下代码:

from tastypie.authorization import Authorization
from tastypie.exceptions import Unauthorized


class UserObjectsOnlyAuthorization(Authorization):
    def read_list(self, object_list, bundle):
        # This assumes a ``QuerySet`` from ``ModelResource``.
        return object_list.filter(user=bundle.request.user)

    def read_detail(self, object_list, bundle):
        # Is the requested object owned by the user?
        return bundle.obj.user == bundle.request.user

    def create_list(self, object_list, bundle):
        # Assuming they're auto-assigned to ``user``.
        return object_list

    def create_detail(self, object_list, bundle):
        return bundle.obj.user == bundle.request.user

    def update_list(self, object_list, bundle):
        allowed = []

        # Since they may not all be saved, iterate over them.
        for obj in object_list:
             if obj.user == bundle.request.user:
                allowed.append(obj)

        return allowed

    def update_detail(self, object_list, bundle):
        return bundle.obj.user == bundle.request.user

    def delete_list(self, object_list, bundle):
        # Sorry user, no deletes for you!
        raise Unauthorized("Sorry, no deletes.")

    def delete_detail(self, object_list, bundle):
        raise Unauthorized("Sorry, no deletes.")

如果我将此身份验证应用于 api.py 中的 UserResource,就像我为 EntryResource 所做的那样,它会给我报错。如有必要,我可以提供更多详细信息。

2、解决方案

要解决这个问题,您可以定义一个新的 CustomUserAuthorization,并在其中添加一个只允许当前用户访问其信息的过滤器。以下是如何实现的:

from tastypie.authorization import Authorization
from tastypie.exceptions import Unauthorized


class CustomUserAuthorization(Authorization):
    def read_list(self, object_list, bundle):
        # This you put your filter
        return object_list.filter(id=bundle.request.user.id)

    def read_detail(self, object_list, bundle):
        # This is to check the current user
        return bundle.obj.id == bundle.request.user.id

    def create_list(self, object_list, bundle):
        raise Unauthorized("Sorry, not allowed.")

    def create_detail(self, object_list, bundle):
        raise Unauthorized("Sorry, not allowed.")

    def update_list(self, object_list, bundle):
        raise Unauthorized("Sorry, not allowed.")

    def update_detail(self, object_list, bundle):
        # Only update your details
        return bundle.obj.id== bundle.request.user.id

    def delete_list(self, object_list, bundle):
        raise Unauthorized("Sorry, no deletes.")

    def delete_detail(self, object_list, bundle):
        raise Unauthorized("Sorry, no deletes.")

在 api.py 中,您可以将此 CustomUserAuthorization 应用于 UserResource:

class UserResource(ModelResource):
    class Meta:
        queryset = User.objects.all()
        excludes = ['password', 'is_superuser']
        resource_name = 'user'
        authentication=MultiAuthentication(SessionAuthentication(),ApiKeyAuthentication())
        authorization=CustomUserAuthorization()
        allow_methods=['get']

这样,只有当前用户才能访问其自己的信息。其他用户将无法访问任何数据。

希望这个解决方案能够帮助您解决问题。