【问题标题】:Django Rest Framework permission on a Foreign key item外键项的 Django Rest Framework 权限
【发布时间】:2017-09-04 18:56:42
【问题描述】:

我有两个模型有这样的关系:

class ManuscriptItem(models.Model):
    """Represents a single manuscript's content"""

    author = models.ForeignKey('accounts_api.UserProfile', on_delete=models.CASCADE)
    title = models.CharField(max_length=255)
    content = models.CharField(max_length=99999999)

    def __str__(self):
        """Django uses when it needs to convert the object to a string"""
        return str(self.id)


class ManuscriptLibrary(models.Model):
    """Represents a single manuscript's library"""

    manuscript = models.OneToOneField(ManuscriptItem, on_delete=models.CASCADE)
    bookmarks = models.CharField(max_length=99999999)
    history = models.CharField(max_length=99999999)

    def __str__(self):
        """Django uses when it needs to convert the object to a string"""
        return str(self.manuscript)

我只想让 ManuscriptItem Author 能够分配一个 该 ManuscriptItem 的 ManuscriptLibrary。

以下是我尝试过但没有成功的一些方法:

class PostOwnManuscriptLibrary(permissions.BasePermission):
    """Allow users to update their own manuscripts libraries."""

    def has_object_permission(self, request, view, obj):
        return obj.manuscript.author.id == request.user.id

结果:每个人都可以写入任何他们不是他们的 ManuscriptItem 作者。

class PostOwnManuscriptLibrary(permissions.BasePermission):
    def has_permission(self, request, view):
        manuscript = ManuscriptLibrary.objects.filter(manuscript__author=request.user.id).exists()
        return manuscript

结果:没有人拥有任何权限,甚至他们自己的作者也没有 手稿。

相关的API端点视图如下:

class ManuscriptViewSet(viewsets.ModelViewSet):
    """Handles creating, reading and updating items."""

    authentication_classes = (TokenAuthentication,)
    serializer_class = serializers.ManuscriptItemSerializer
    permission_classes = (permissions.PostOwnManuscript, IsAuthenticated,)

    def perform_create(self, serializer):
        """Sets the user profile to the logged in user."""
        serializer.save(author=self.request.user)

    def get_queryset(self):
        """
        This view should return a list of all the manuscripts
        for the currently authenticated user.
        """
        user = self.request.user
        return models.ManuscriptItem.objects.filter(author=user)


class ManuscriptLibraryViewSet(viewsets.ModelViewSet):
    """Handles creating, reading and updating manuscript library."""

    authentication_classes = (TokenAuthentication,)
    serializer_class = serializers.ManuscriptLibrarySerializer
    permission_classes = (permissions.PostOwnManuscriptLibrary,)

    def get_queryset(self):
        """
        This view should return a list of all the manuscripts settings
        where the manuscript author is the logged in user
        """
        user = self.request.user
        return models.ManuscriptLibrary.objects.filter(manuscript__author=user)

附加信息:

我已经覆盖了我的用户模型,因此在我的 settings.py 中包括:

# Takes the model and assigns it!
AUTH_USER_MODEL = 'profiles_api.UserProfile'

在我的用户个人资料 API 中

class UserProfile(AbstractBaseUser, PermissionsMixin):
    """Represents a "user profile" inside our system."""

    email = models.EmailField(max_length=255, unique=True)
    name = models.CharField(max_length=255)
    is_active = models.BooleanField(default=True)
    is_staff = models.BooleanField(default=False)

    objects = UserProfileManager()

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['name']

    def get_full_name(self):
        """Used to get a users full name."""

        return self.name

    def get_short_name(self):
        """Used to get a users short name."""

        return self.name

    def __str__(self):
        """Django uses this when it needs to convert the object to a string"""

        return self.email

修复:

根据 BearBrown 的建议进行了调整,需要查询 正确的模型:

class PostOwnManuscriptLibrary(permissions.BasePermission):
    """Allow users to update their own manuscripts libraries."""

    def has_object_permission(self, request, view, obj):
        if request.method in permissions.SAFE_METHODS:
            return True
        return obj.manuscript.author == request.user

    def has_permission(self, request, view):
        if request.method == 'POST':
            manuscript = request.data.get('manuscript')
            print(manuscript)
            instance = ManuscriptItem.objects.get(pk=manuscript)
            return instance.author == request.user
        return True

【问题讨论】:

  • 请显示您的查看代码
  • 更新了@BearBrown
  • request.user 是默认的 Django 用户模型实例吗?
  • 不是作者的人能看到ManuscriptItemManuscriptLibrary吗?您按当前登录用户过滤查询集,如果不是作者,则按您的代码过滤您必须得到 404 错误
  • 请将此信息添加到问题中。

标签: django django-models django-rest-framework django-views django-permissions


【解决方案1】:

我想你可以试试这个:

class PostOwnManuscriptLibrary(permissions.BasePermission):
    """Allow users to update their own manuscripts libraries."""

    def has_object_permission(self, request, view, obj):
        if request.method in permissions.SAFE_METHODS:
            return True
        return obj.manuscript.author == request.user

    def has_permission(self, request, view):
        if request.method == 'POST':
            manuscript = request.data.get('manuscript')
            instance = ManuscriptLibrary.objects.get(pk=manuscript)
            return instance.author == request.user
         return True

当您完成“POST”后,从请求中获取 manuscript 数据并使用 request.author 使 ManuscriptLibrary.author 无效

查看

class ManuscriptLibraryViewSet(viewsets.ModelViewSet):
    """Handles creating, reading and updating manuscript library."""

    authentication_classes = (TokenAuthentication,)
    serializer_class = serializers.ManuscriptLibrarySerializer
    queryset = models.ManuscriptLibrary.objects.all()
    permission_classes = (permissions.PostOwnManuscriptLibrary,)

【讨论】:

  • 我可以将图书馆发布到手稿,但仍然与不应被允许的作者合作。
  • 尝试新版本
  • 我想我们已经很接近了,这是我没有尝试过的。我也得到了这个项目/manuscripts_api/permissions.py",第 30 行,在 has_permission 实例 = ManuscriptLibrary.objects.get(pk=manuscript)。手稿_api.models.DoesNotExist:ManuscriptLibrary 匹配查询不存在。----我是现在看这个看看
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-17
  • 2014-01-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多