rest_framework viewsets.ViewSet 的簡單使用


前言:rest_framework 在引進視圖類的時候, 有很多人都是使用 django的路由指向方式, 將其指向具體的視圖類。但是在rest_framework 中, 可以通過路由指向,具體的指向路由中的具體方法。

先簡單說一下 ViewSet 中實現了幾個方法。

list  #get 請求 返回全部查詢
create  #post 請求 處理表單提交數據
retrieve #get 請求 通過pk 查詢單個信息
update  #patch 請求 通過pk 修改數據
destroy  #delete 請求 通過pk 刪除數據

 

ok, 下面就上代碼了。

首先,我們需要進行創建一個model,只是簡單舉例(主鍵ID ,不需要指定。數據庫自動會創建。)

from django.db import models
from django.contrib.auth.models import AbstractUser
# Create your models here.


class User(models.Model, models.Manager):

    class Meta:
        db_table = 'user'

    username = models.CharField(db_column='username', max_length=128, null=True)
    text = models.CharField(db_column='text', max_length=128, null=True)
    token = models.CharField(db_column='token', max_length=128, null=True)

 

第二,創建序列化器。這個也是rest_framework的精髓了,也是大部分人用它的理由,它可以將你的數據進行整和,返回字典類型(也有其他類型),方便我們拿取。

from rest_framework import serializers
from .models import User

class UserSerializers(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ['username', 'text', 'token']

    def create(self, validated_data):
        print(validated_data,'~~~~~~~~')
        return User.objects.create(**validated_data)



    def update(self, instance, validated_data):

        instance.username = validated_data.get('username')
        instance.text = validated_data.get('text')
        instance.save()
        return instance

第三,創建視圖類 *** (實現了登錄認證,和權限判定)

from rest_framework.views import APIView, status
from rest_framework.response import Response
from .serializers import UserSerializers
from rest_framework import viewsets
from rest_framework.authentication import BaseAuthentication
from rest_framework.permissions import BasePermission
from .models import User
from rest_framework.exceptions import AuthenticationFailed
from django.shortcuts import redirect
import jwt
from rest_framework.decorators import action

# 注冊函數,將提交的username 和 password 保存到數據庫,
# 並且使用jwt, 生成用戶的token。也就是大家常說的cookie。
class Register(APIView): def get_obj(self): try: return User.objects.all() except: return status.HTTP_404_NOT_FOUND def post(self, request): payload = UserSerializers(data=request.data) if payload.initial_data.get('username') not in self.get_obj(): jwt_token = jwt.encode(payload={'id':1}, key='123', algorithm='HS256').decode('utf8') if payload.is_valid(): payload.validated_data['token'] = jwt_token payload.save() return Response(data={'ok':'注冊成功'}) else: return redirect(to=LoginAuth) return Response(data={})

# 登陸驗證, 要繼承 BaseAuthentication ,這個積累里面實現了
# authentication 和 authentication_header 方法,
# 所以我們自己重寫這兩個方法,這樣他在運行的時候就會先調用我們自己創建的,
# 然后說一下,大家不要擔心這個函數定義完了,沒有調用。他是自動的調用的這個類的方法的,不需要特別指定調用。
# 只要在下面的視圖函數中加上類屬性就可以了。
authentication_classes = [LoginAuth,](登陸驗證)
# permission_classes = [LoginPremission,](權限驗證) 在類中指明,
# 這兩個方式即可自動調用了,可以看一下IndexViewSet這個視圖類是怎么指明要調用驗證和權限判定的,
# 大家在使用postman 或者其他 測試 的時候 可以將這兩句注釋調,要不然你就需要生成token。
class LoginAuth(BaseAuthentication): """ All authentication classes should extend BaseAuthentication. """

    def authenticate(self, request): """ Authenticate the request and return a two-tuple of (user, token). """ token = request.query_params.get('token') if token: user_obj = User.objects.filter(token=token).first() if user_obj: return user_obj, token else: raise AuthenticationFailed('無效') else: raise AuthenticationFailed("沒有token.") def authenticate_header(self, request): pass


# 登陸權限驗證,和上面的認真基類一樣, BassePermission 也實現特定的兩個方法 has_permission
# 和 has_object_permission 也是會自動調用的, 然會 request.auth 是去驗證token的,
# 你也可以在這個函數中自己定義權限驗證,比如request.name == '1'. 就是管理員之類的。
# 然后返回True 表示驗證通過。 False 標識驗證不通過。 class LoginPremission(BasePermission): def has_permission(self, request, view): """ Return `True` if permission is granted, `False` otherwise. """ if request.auth: return True else: return False def has_object_permission(self, request, view, obj): """ Return `True` if permission is granted, `False` otherwise. """ pass
# 最重要的視圖函數了 class IndexViewSet(viewsets.ViewSet): # authentication_classes = [LoginAuth,] # permission_classes = [LoginPremission,] queryset = User.objects.all() serializer_class = UserSerializers def list(self, request): """ get 請求 返回全部查詢 :param request: :return: """ print('list') return Response(data='list') def create(self, request): """ post 請求 處理表單提交數據 :param request: :return: """ print('create') return Response(data='create') def retrieve(self, request, pk=None): """ get 請求 通過pk 查詢單個信息 :param request: :param pk: :return: """ print('retrieve') return Response(data='retrieve') def update(self, request, pk=None): """ patch 請求 通過pk 修改數據 :param request: :param pk: :return: """ print('update') return Response(data='update') def destroy(self, request, pk=None): """ delete 請求 通過pk 刪除數據 :param request: :param pk: :return: """ print('destroy') return Response('destroy')

最后,指定路由,綁定視圖類中對應的方法(官方提供了很多方式去綁定路由和視圖函數,這里小編提供一個)


from
django.urls import path from rest_framework.urlpatterns import format_suffix_patterns from rest_framework import routers from .views import IndexViewSet

# 在這里着重說一下 path(‘’,IndexViewSet.as_view({'get':'list'}))
#          path(路由,綁定的試圖類.as_view({請求方式:綁定的視圖類中具體的方法}))
          
urlpatterns
= format_suffix_patterns([ path('', IndexViewSet.as_view({'get': 'list'})), path('<int:pk>/', IndexViewSet.as_view({'get': 'retrieve'})), path('post/',IndexViewSet.as_view({'post': 'create'})), path('patch/<int:pk>/',IndexViewSet.as_view({'patch':'update'})), path('destroy/<int:pk>/', IndexViewSet.as_view({'delete':'destroy'})) ])

 

rest_framework官方文檔:https://www.django-rest-framework.org/

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM