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/
邮箱: 1090055252@qq.com