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/

 

posted @ 2020-06-19 17:27  Black_Climber  阅读(1278)  评论(0编辑  收藏  举报