【问题标题】:How to change permissions depend on different instance using Django Rest Framework?如何更改权限取决于使用 Django Rest Framework 的不同实例?
【发布时间】:2016-07-11 17:47:55
【问题描述】:

我用的是Django rest框架,我的模型是这样的,每个Act可以有多个post。

class Act(models.Model):
    user = models.ForeignKey("common.MyUser", related_name="act_user")
    act_title = models.CharField(max_length=30)
    act_content = models.CharField(max_length=1000)
    act_type = models.IntField()
   

class Post(models.Model):
    user = models.ForeignKey("common.MyUser", related_name="post_user")
    act = models.ForeignKey("activities.Act", related_name="post_act")
    post_title = models.CharField(max_length=30, blank=True)
    post_content = models.CharField(max_length=140)

我在 DRF 中的 view.py:

class PostList(generics.ListCreateAPIView):
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,)
    queryset = Post.objects.all()
    serializer_class = PostAllSerializer

    def perform_create(self, serializer): #self is a instance of class or is a class here?
        serializer.save(user=self.request.user)

这很好用,但我现在想要的是如果 act_type = 1 意味着这是一个私人行为,只有行为作者可以在这个行为下创建帖子。我想知道如何使用不同的权限类取决于不同的行为。也许看起来像:

class PostList(generics.ListCreateAPIView):
    if self.act_type == 1:
        permission_classes = (permissions.IsAuthenticatedOrReadOnly,IsActCreatorOrReadOnly)
    else
        permission_classes = (permissions.IsAuthenticatedOrReadOnly,)
    queryset = Post.objects.all()
    serializer_class = PostAllSerializer

    def perform_create(self, serializer): #self is a instance of class or is a class here?
        serializer.save(user=self.request.user)

而且我也想知道这个permissions.py怎么写:

class IsActCreatorOrReadOnly(permissions.BasePermission):
    """
    Custom permission to only allow owners of an object to edit it.
    """
    def has_object_permission(self, request, view, obj):
        if request.method in permissions.SAFE_METHODS:
            return True

        return obj.act.user == request.user

我不知道 obj 在这里的真正含义,错误告诉我 obj.act 不存在。

编辑

这是我的 postSerializer。

class PostAllSerializer(serializers.ModelSerializer):
    """Posts api fields"""
    post_user = UserSerializer(source="user", read_only=True)
    post_author = serializers.ReadOnlyField(source='user.user_name')
    
    class Meta:
        model = Post
        fields = ("id", "act", "post_author", "post_title", "post_content",) 
       

我试过了,但没有用,即使我不是该法案的作者,我仍然可以创建帖子(但 act_id 错误):

def create(self, request, *args, **kwargs):
    act_type = request.data.get("act_type") 
    if act_type == 0:
        act_id = request.data.get("act")
        act = Act.objects.get(pk=act_id)
        if request.user != act.user:
            return Response(status=403)
    return super().create(request)

【问题讨论】:

  • 你能把PostSerializer的代码贴出来吗?

标签: python django django-rest-framework


【解决方案1】:

对于使用不同的权限类,您可以在 PostList 视图上覆盖 get_permissions 方法:

def get_permissions(self):
    if self.request.method == 'POST':
        return (OnePermission(),)
    elif  # other condition if you have:
        return (AnotherPermission(),)
    return (YetAnotherPermission(),)

但是,在您的情况下,您不能使用对象级别权限,因为您还没有对象实例。来自 DRF docs(我的亮点):

REST 框架权限还支持对象级权限。对象级权限用于确定是否应允许用户对特定对象进行操作,该对象通常是模型实例。 调用 .get_object() 时,对象级权限由 REST 框架的通用视图运行。

在进行POST 请求时,您还没有任何对象,因此不会调用对象级别的权限。

实现所需的一种方法是在PostList 视图的create 方法中检查它。像这样的东西(假设代码):

class PostList(generics.ListCreateAPIView):
    ...

    def create(self, request):
        act_id = request.data.get('act')  # depending on your PostSerializer, the logic of getting act id can vary a little
        act = Act.objects.get(pk=act_id)  # assuming act always exists, otherwise account for in-existing act
        if act.user != request.user:
            return Response({details: "You shall not pass!!!", status=200)  # change to a status and message you need here

        # logic of Post creation here

祝你好运!

【讨论】:

  • 谢谢 iulian,我会编辑我的帖子,但还是不行。
  • 您具体编辑了什么?有什么改变吗?问题出在哪里?
  • 我添加了 PostSerializer.py 并添加了我之前没有覆盖的“create”方法。
  • 是您的common.MyUser 类,是项目的AUTH_USER_MODEL,还是您有与MyUser 有关系的标准用户模型?
猜你喜欢
  • 2021-03-17
  • 1970-01-01
  • 2021-05-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-21
  • 2019-05-10
  • 1970-01-01
相关资源
最近更新 更多