1. 程式人生 > 程式設計 >Restframework從入門到精通(三):Restframework之許可權設定

Restframework從入門到精通(三):Restframework之許可權設定

第一步:增加顯示操作人

檢視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","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驗證,所以這裡留個坑,到時候我做個專案案例回來填