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,我们且看看它的源码,你就明白了
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<pk>\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路由,有多个注册多个即可

posted @ 2018-10-31 19:15  lvye001  阅读(659)  评论(3编辑  收藏  举报