Restframework从入门到精通(三):Restframework之权限设置

567 阅读4分钟

第一步:增加显示操作人

查看API的这个界面默认是要登陆的,因为我上面我使用了admin账号去登陆,所以i才可以显示这个页面

但是默认的是所有账号登陆进去都可以对API进行增删改查,这个完全不符合逻辑。正常的逻辑是谁创建的才能谁去改,没有身份验证进去的只能读取操作。

如图,是我去数据库把我的session信息删掉之后再查看API的结果

依照官网的文档演示步骤,要先在model创建一个外键字段

......
class Publish(models.Model):
    name=models.CharField(max_length=20,verbose_name="出版社名称",unique=True)
    address=models.CharField(max_length=128,verbose_name="地址")
    operator = models.ForeignKey('auth.User', on_delete=models.CASCADE)

......

因为添加了一个字段,所以要进行数据库的迁移:makemigrations -> migrate

这里因为添加了一个字段,而之前的字段没有这个字段的默认值,所以会出现错误,要把默认值赋值为1即可

使用如上操作之后在数据库就已经生成了新的operator字段了,所以接下来要对序列化的文件也添加这个字段

class Publishserializer(serializers.ModelSerializer):
    class Meta:
        model=Publish
        fields=(
            "id",
            "name",
            "address",
            "operator"
        )
        ......

再登陆admin账号查看API得到的结果应该如下:

这个得到的operator的结果都为1是当然没问题的,ID1就是代表admin账号,但是我们要显示的是这个ID的用户名

所以我们要在序列化文件里面添加一个字段

class Publishserializer(serializers.ModelSerializer):
    operator=serializers.ReadOnlyField(source="operator.username")
    class Meta:
        model=Publish
        fields=(
            "id",
            "name",
            "address",
            "operator"
        )

第二步:权限设置

关于权限设置在官网都有详细的说明

权限说明文档

依照文档的说法,我们要在视图文件里面添加一个字段,使得未登录的用户只具有读取权限,登录的用户才具有读写权限:

from rest_framework import permissions
....
class Publish_list(generics.ListCreateAPIView):
    queryset = Publish.objects.all()
    serializer_class = Publishserializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,)

class PublisherDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Publish.objects.all()
    serializer_class = Publishserializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,)

去演示一下,会发现未登录用户只有读取权限,登陆的用户才有写权限

这个permissions字段有好几种,在文档的API的权限设置详细文档里面有说明

权限设置详细文档

在这里因为我要设置的是谁录入的API谁才具有读写权限,所以这里我要用的是对象级别权限

如图所示:

依照文档的说法,我们要新建一个permissions.py文件

permissions.py

from rest_framework import permissions


class IsOwnerOrReadOnly(permissions.BasePermission):
    """
    自定义权限只允许对象的权限来去编辑他
    """

    def has_object_permission(self, request, view, obj):
        # 读取权限允许任何请求
        # 所以我们总是允许Get,HEAD和OPTIONS请求
        if request.method in permissions.SAFE_METHODS:
            return True

        # 只有该出版社的所有者才允许去读写
        return obj.operator == request.user

然后再去视图函数里面继承permissions的这个类

之后我们再去创建一个管理员账号admin2看看能不能修改admin的API

image-20191031113108165

哦吼,大功告成

第三步:新建保存operator值的方法

还有最后的一个问题,假如我们新建一个用户,就拿刚刚创建的admin2来说,我创建一个新的API数据,但是我的operatorID是没有的。

我之前创建的admin账号是我模型迁移之前设置了默认的值1,但是我新创建的admin2没有operator的值,所以我们还要创建一个类方法去编写

我通俗的将不太好懂,这个原理如下:

使用post去创建一个新的API的时候是通过序列化去添加的,而我的序列化代码如下

序列化没有自己的save方法,默认存储方法是在ModelSerializer里面的,也就是在Model里面保存,但是我新建的用户admin2添加一个字段,他的operator_id都不知道去哪里找,如果使用admin2去添加API数据的话,会出现如下情况:

对于这种情况,文档的说明如下:

即是让我们在视图文件创建一个.perform_create方法

views.py

class Publish_list(generics.ListCreateAPIView):
    queryset = Publish.objects.all()
    serializer_class = Publishserializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,IsOwnerOrReadOnly)

    def perform_create(self, serializer):
        serializer.save(operator=self.request.user)

好了现在再去试一下使用admin2去post请求

完美,搞定

留坑

项目开发可能更多用到的是token验证,所以这里留个坑,到时候我做个项目案例回来填