Django-DRF-视图的演变
版本一(基于类视图APIView类)
views.py:
APIView是继承的Django View视图的。
1 from .serializers import UserSerializers #导入当前目录配置好的序列化器 2 from .models import User #导入数据库 3 from rest_framework.views import APIView #导入APIView 4 from rest_framework.response import Response #该模块返回json数据 5 from rest_framework import status #内置状态码模块 6 7 class UserAPIView(APIView): #查看所有及添加数据视图 8 def get(self,request): 9 users = User.objects.all() #获取数据库里所有数据 10 ser = UserSerializers(instance=users,many=True) #进行序列化操作,指定更多集合对象 11 return Response(ser.data,status=200)#返回成功数据 12 13 def post(self,request): #添加数据 14 ser = UserSerializers(data=request.data)#接收前台传输数据 15 if ser.is_valid(): #判断书否合法raise_exception=True加次参数表示不合法抛出异常,默认false 16 ser.save() #保存 17 return Response(ser.data,status=200) 18 return Response(ser.errors) #返回错误信息 19 20 class UserSingleView(APIView): #单条查询,改,删除视图 21 def get(self,request,pk): 22 user = User.objects.get(id=pk) #查询单条集合对象 23 ser = UserSerializers(instance=user)#序列化数据 24 return Response(ser.data) 25 26 def put(self,request,pk): #修改 27 user = User.objects.get(pk=pk) 28 ser = UserSerializers(instance=user,data=request.data) #注意指定参数 29 if ser.is_valid(): 30 ser.save() 31 return Response(ser.data,status=200) 32 return Response(ser.errors) 33 34 def delete(self,request,pk): #删除操作 35 User.objects.get(pk=pk).delete() 36 return Response(status=status.HTTP_200_OK)
代码说明:
1. 使用类视图,定义两个类并继承APIView类视图;
2. 在类视图里编写:增删改查方法,通过HttpResponse返回状态。
serializers.py
from rest_framework import serializers #导入序列
from .models import User #导入表
class UserSerializers(serializers.Serializer):#注意继承的类 nick_name = serializers.CharField(max_length=20,required=True) #required=True设置必须验证 gender = serializers.BooleanField(default=0,required=False) def create(self, validated_data): #创建数据的操作 return User.objects.create(**validated_data) def update(self, instance, validated_data):#修改数据的操作
instance接收的是数据库查询的单个对象,validated_data为前端传输的数据
instance.nick_name = validated_data.get('nick_name',instance.nick_name) instance.gender = validated_data.get('gender',instance.gender) instance.save() #取出值每个字段进行保存 return instance
版本二(使用混合 mixins)
继承generics和mixins里的方法,称之为“混合”
views.py:
1 from rest_framework import mixins, generics # 导入相应模块 2 # mixins就是一个类,只不过这个类里定义了很多操作数据的方法 3 from .serializers import UserModelSerializer 4 class UserGenericAPIview(generics.GenericAPIView,mixins.ListModelMixin,mixins.CreateModelMixin): 5 queryset = UserInfo.objects.all() # queryset指定集合数据是从哪个数据库来 6 serializer_class =UserModelSerializer # serializer_class配置序列化器类UserModelSerializer 7 8 # 调用mixins.ListModelMixin类的list()方法 9 def get(self,request): 10 return self.list(request) 11 12 # 调用mixins.CreateModelMixin类的create()方法 13 def post(self,request): 14 return self.create(request) 15 16 class UserGenericSingleView(generics.GenericAPIView,mixins.RetrieveModelMixin,mixins.UpdateModelMixin,mixins.DestroyModelMixin): 17 queryset = UserInfo.objects.all() 18 serializer_class = UserModelSerializer 19 20 # 调用mixins.RetrieveModelMixin类的retrieve()方法 21 def get(self,request,pk): #检索 22 return self.retrieve(request) 23 24 # 调用mixins.UpdateModelMixin类的update()方法 25 def put(self,request,pk): #修改 26 return self.update(request) 27 28 # 调用mixins.DestroyModelMixin类的destroy()方法 29 def delete(self,request,pk): #破坏 30 return self.destroy(request)
代码说明:
1. 为什么要继承mixins.RetrieveModelMixin,mixins.UpdateModelMixin,mixins.DestroyModelMixin等这一堆方法呢?
答:比如我们自定义写了delete方法,而这个方法会自动、只能的去调用mixins.DestroyModelMixin这个类里面的动作。
serializers,py
1 from rest_framework import serializers 2 from .models import UserInfo 3 4 class UserModelSerializer(serializers.ModelSerializer): 5 class Meta: 6 #配置model为UserInfo 7 model = UserInfo 8 fields = "__all__" #fields配置要序列化的字段,"__all__"表示所有的字段都序列化
在上个版本中,queryset和serializer属性都是通过自己声明去使用的;
这个版本继承使用混合继承了generics,通过查看generics源码发现如下:
class GenericAPIView(views.APIView): ··· queryset = None serializer_class = None ···
版本三(使用混合高级版)
views.py:
1 from rest_framework import generics 2 3 class UserListAPIView(generics.ListCreateAPIView): 4 queryset = UserInfo.objects.all() 5 serializer_class = UserModelSerializer 6 7 class UserSingleView(generics.RetrieveUpdateDestroyAPIView): 8 queryset = UserInfo.objects.all() 9 serializer_class = UserModelSerializer
这几行代码搞定上面所有功能,只需要传入queryset和serializer即可,这什么原理呢?
1、第二版本中,我们继承了generics.GenericAPIView类视图,自己写了两个get和post方法对吧,那generics的另一个方法把这两个事情也干了,我们只需要继承即可。
2、对的,这个方法就是generics.ListCreateAPIView,我们且看看它的源码,你就明白了
2、对的,这个方法就是generics.ListCreateAPIView,我们且看看它的源码,你就明白了
class ListCreateAPIView(mixins.ListModelMixin, mixins.CreateModelMixin, GenericAPIView): """ Concrete view for listing a queryset or creating a model instance. """ def get(self, request, *args, **kwargs): return self.list(request, *args, **kwargs) def post(self, request, *args, **kwargs): return self.create(request, *args, **kwargs)
版本四(视图集 ViewSet)
views.py:
1 from rest_framework import viewsets,mixins 2 class GennericViewsSet(viewsets.GenericViewSet, 3 mixins.CreateModelMixin, 4 mixins.ListModelMixin, 5 mixins.RetrieveModelMixin, 6 mixins.UpdateModelMixin, 7 mixins.DestroyModelMixin 8 ): 9 queryset = UserInfo.objects.all() 10 serializer_class = Userserializer
这个版本views里就写了一个类视图,之前的所有版本都是写一个List和一个Detail视图的,
这个类 继承了viewsets.GenericViewSet,其他的方法都是mixins的viewsets
GenericViewSet继承了ViewSetMixin方法,从ViewSetMixin的源码里能看到可以改写as_view的信息,来达到定制路由的效果
class ViewSetMixin(object): @classonlymethod def as_view(cls, actions=None, **initkwargs): ······ if not actions: raise TypeError("The `actions` argument must be provided when " "calling `.as_view()` on a ViewSet. For example " "`.as_view({'get': 'list'})`")
urls.py:
1 from django.conf.urls import url 2 from . import views 3 4 urlpatterns = [ 5 url(r'^$',views.GennericViewsSet.as_view({'get':'list',"post": "create"})), #注意这里的写法 6 url(r'^users/(?P\d+)/$',views.GennericViewsSet.as_view({'get':'retrieve','put':'update','delete':'destroy'})) 7 ]
版本五 (终极大法:写项目选用此法)
views.py:
1 from rest_framework.viewsets import ModelViewSet 2 class ZhongJiBanView(ModelViewSet): 3 queryset = UserInfo.objects.all() 4 serializer_class = UserModelSerializer
直接继承了一个巨无霸(ModelViewSet),这个巨无霸将所有的功能都封装到一块。相当于把我们从第一版到第三版写的所有事情都干了,
按照老规矩,我们来看看它的源码:
class ModelViewSet(mixins.CreateModelMixin, mixins.RetrieveModelMixin, mixins.UpdateModelMixin, mixins.DestroyModelMixin, mixins.ListModelMixin, GenericViewSet): """ A viewset that provides default `create()`, `retrieve()`, `update()`, `partial_update()`, `destroy()` and `list()` actions. """ pass
从源码中能看出,ModelViewSet所继承的视图类
urls.py
1 from . import views 2 from rest_framework.routers import DefaultRouter 3 rount = DefaultRouter() 4 rount.register('user',views.ZhongjiBanView) 5 urlpatterns = [] 6 urlpatterns += rount.urls
最终版的规则使用了drf的DefaultRouter函数,通过实例化DefaultRouter得到route对象,使用route.register()你的app路由,有多个注册多个即可