博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
第四章 restframework——视图组件
阅读量:4453 次
发布时间:2019-06-07

本文共 11970 字,大约阅读时间需要 39 分钟。

第四章 restframework——视图组件

 

一、基本视图

二、mixin模块+generics模块(GenericAPIView类)编写视图

三、generics模块下的ListCreateAPIView,RetrieveUpdateDestroyAPIView

四、viewsets模块下的ModelViewSet

 

一、基本视图

 回顾上一章节的序列化组件,你会发现views里的代码逻辑部分大同小异

代码如下:

from django.db import models# Create your models here.from django.db import models# Create your models here.class Book(models.Model):    title=models.CharField(max_length=32)    price=models.IntegerField()    pub_date=models.DateField()    publish=models.ForeignKey("Publish")    authors=models.ManyToManyField("Author")    def __str__(self):        return self.titleclass Publish(models.Model):    name=models.CharField(max_length=32)    email=models.EmailField()    # def __str__(self):    #     return self.nameclass Author(models.Model):    name=models.CharField(max_length=32)    age=models.IntegerField()    def __str__(self):        return self.name
models.py

urls.py

urlpatterns = [    url(r'^admin/', admin.site.urls),    url(r'^publishes/$',views.PublishView.as_view()),    url(r'^publishes/(?P
\d+)/$',views.PublishDetailView.as_view(),name='publish_detail'), url(r'^books/$',views.BookView.as_view()), url(r'^books/(\d+)/$',views.BookDetailView.as_view())]
from django.shortcuts import *from django.views import Viewfrom .models import *import json# Create your views here.from rest_framework.views import APIViewfrom rest_framework.response import Responsefrom .all_serializers import *# class BookSerializers(serializers.Serializer):#     title = serializers.CharField(max_length=32)#     price = serializers.IntegerField()#     pub_date = serializers.DateField()#     publish = serializers.CharField(source="publish.name")#     # authors=serializers.CharField(source="authors.all") #这样会返回queryset对象,看起来还不是特别舒服#     authors = serializers.SerializerMethodField() # 这个方法只是为多对多服务的,下面要写类似钩子的方法#     def get_authors(self,obj):#         temp = []#         for obj in obj.authors.all():#             temp.append(obj.name)#         return tempclass BookView(APIView):    def get(self,request):        # get请求数据        book_list = Book.objects.all()        bs = BookModelSerializers(book_list,many=True)        '''        序列化BookSerializers(book_list,many=True)做了如下操作:        temp = []        for obj in book_list:            temp.append({                "title":obj.title,                "price":obj.price,                "pub_date":obj.pub_date,                "publish":obj.publish,   # 这里的返回值就是上面get_authors的返回值            })                          '''        return Response(bs.data)    def post(self,request):        # post请求数据        bs = BookModelSerializers(data=request.data)        if bs.is_valid():            print(bs.validated_data)            bs.save()  # create方法            return Response(bs.data)        else:            return HttpResponse(bs.errors)class BookDetailView(APIView):    def get(self,request,id):        book = Book.objects.filter(pk=id).first()        bs = BookModelSerializers(book)        return Response(bs.data)    def put(self,request,id):        book = Book.objects.filter(pk=id).first()        # 因为是做更新操作,所以要写data=request.data,把新数据放进去        bs = BookModelSerializers(book,data=request.data)        if bs.is_valid():            bs.save()            return Response(bs.data)        else:            return Response(bs.errors)    def delete(self,request,id):        Book.objects.filter(pk=id).delete()        # 删除操作返回空即可        return Response()class PublishView(APIView):    def get(self, request):        publish_list = Publish.objects.all()        ps = PublishModelSerializers(publish_list, many=True)        return Response(ps.data)        # 取数据        # print('restframework', request.data)        # print('restframework type', type(request.data))        # print('restframework', request._request.GET)        # print('restframework type', type(request._request.GET))        # print('restframework', request.GET)        # print('restframework type', type(request.GET))        # return HttpResponse('ok')        # 序列化        # publish_list = Publish.objects.all()    #queryset对象        # pb = PublishSerializers(publish_list, many=True)        # many = true 代表前面传入的参数是queryset对象        # print(pb.data)        # publish1 = Publish.objects.filter(pk=1).first()        # print(publish1)        # publish对象        # pb = PublishSerializers(publish1,many=False)        # PublishSerializers(model_obj,many = false)        # many = false 代表前面传入的参数是model对象        # 默认many = false,所以如果是model对象可以不用写many        # print(pb.data)        # return HttpResponse(pb.data)        # 方式一        # publish_list = list(Publish.objects.all().values('name','email'))        # return HttpResponse(json.dumps(publish_list))        # 方式二        # from django.forms.models import model_to_dict        # publish_list = Publish.objects.all()        # temp = []        # for obj in publish_list:        #     temp.append(model_to_dict(obj))        # return HttpResponse(json.dumps(temp))        # 方式三        # from django.core import serializers        # publish_list = Publish.objects.all()        # temp = serializers.serialize("json",publish_list)        # return HttpResponse(temp)    def post(self, request):        # 取数据        # 原生的request操作        # print('POST',request.POST)        # print('body',request.body)        # print(type(request))        # from django.core.handlers.wsgi import WSGIRequest        # print(request.data)        # 新的request支持的操作        # 要想使用之前request的方法        # ret = request._request.POST        # django将request的所有方法的数据获取进行了不同的封装        # 而restframework将request下POST方法的数据封装成request.data        # print('restframework',request.data)        # print('restframework type',type(request.data))        # return HttpResponse('post')        ps = PublishModelSerializers(data=request.data)        if ps.is_valid():            print(ps.validated_data)            ps.save()  # create方法            return Response(ps.data)        else:            return Response(ps.errors)class PublishDetailView(APIView):    def get(self, request, pk):        publish = Publish.objects.filter(pk=pk).first()        ps = PublishModelSerializers(publish)        return Response(ps.data)    def put(self, request, pk):        publish = Publish.objects.filter(pk=pk).first()        ps = PublishModelSerializers(publish, data=request.data)        if ps.is_valid():            ps.save()            return Response(ps.data)        else:            return Response(ps.errors)    def delete(self, request, pk):        Publish.objects.filter(pk=pk).delete()        return Response()
views.py
from rest_framework import serializersfrom .models import *# 为queryset,model对象做序列化# class PublishSerializers(serializers.Serializer):#     # 下面写的字段取决于你需要哪些字段做序列化#     name = serializers.CharField()#     email = serializers.CharField()class PublishModelSerializers(serializers.ModelSerializer):    class Meta:        model=Publish        fields="__all__"class BookModelSerializers(serializers.ModelSerializer):    class Meta:        model = Book # 表名        fields = "__all__" # 默认把所有字段写入,不包括自己写的get_authors方法        # field = ['nid','title','authors','publish'] # 指定字段        # exclude = ('nid')  # 除了...字段,不能跟fields同时用        # depth = 1 #深度控制,写 几 往里拿几层,层数越多,响应越慢,官方建议0--10之间,个人建议最多3层    # 如果要指定一对多,或多对多显示的字段需要重写create方法    publish = serializers.CharField(source='publish.pk')    authors = serializers.CharField(source="authors.all")    def create(self, validated_data):        # print('validated_data',validated_data)        book = Book.objects.create(            title=validated_data['title'],            price=validated_data['price'],            pub_date=validated_data['pub_date'],            publish_id=validated_data['publish']['pk']        )        book.authors.add(*validated_data['authors'])        return book
all_serializers.py

 

二、mixin模块+generics模块(GenericAPIView类)编写视图

尝试用mixin类写一个AuthorView,对比下它的简便。

【mixin模块】

导入模块

from rest_framework import mixins

先简单熟悉下mixin模块下的几个class,它对应了restful的规范

查看下ListModeMixin的源码,与之前写的get方法对应起来看下

查看下CreateModeMixin的源码,与之前写的get方法对应起来看下

其他的将不再做对比,你会发现其实restframework替我们做了功能封装避免重复代码,那我们用mixin尝试写AuthorView看看

urls.py

urlpatterns = [    url(r'^admin/', admin.site.urls),    url(r'^authors/$',views.AuthorView.as_view(),name='authors'),    url(r'^authors/(?P
\d+)/$',views.AuthorDetailView.as_view(),name='author_detail'), url(r'^publishes/$',views.PublishView.as_view(),name='publishes'), url(r'^publishes/(?P
\d+)/$',views.PublishDetailView.as_view(),name='publish_detail'), url(r'^books/$',views.BookView.as_view(),name='books'), url(r'^books/(\d+)/$',views.BookDetailView.as_view(),name='book_detail'),]

all_serializers.py

class AuthorModelSerializers(serializers.ModelSerializer):    class Meta:        model = Author        fields = "__all__"

 【generics模块

 导入模块

from rest_framework import generics

views.py

注意:

①类必须继承generics.GenericAPIView

②切记:queryset和serializer_class 这两个名字不能改,固定写法,否则会出现如下报错

AssertionError: 'AuthorView' should either include a `queryset` attribute, or override the `get_queryset()` method.

from rest_framework import mixinsfrom rest_framework import genericsclass AuthorView(        mixins.ListModelMixin,        mixins.CreateModelMixin,        generics.GenericAPIView    ):    # GenericAPIView继承了之前的APIView    # !!!切记:queryset和serializer_class 这两个名字不能改!!!    queryset = Author.objects.all()    serializer_class = AuthorModelSerializers    def get(self,request,*args,**kwargs):        return self.list(request,*args,**kwargs)    def post(self,request,*args,**kwargs):        return self.create(request,*args,**kwargs)class AuthorDetailView(        mixins.RetrieveModelMixin,        mixins.DestroyModelMixin,        mixins.UpdateModelMixin,        generics.GenericAPIView    ):    queryset = Author.objects.all()    serializer_class = AuthorModelSerializers    def get(self,request,*args,**kwargs):        return self.retrieve(request,*args,**kwargs)    def put(self,request,*args,**kwargs):        return self.update(request,*args,**kwargs)    def delete(self,request,*args,**kwargs):        return self.destroy(request,*args,**kwargs)

 

四、generics模块下的ListCreateAPIView,RetrieveUpdateDestroyAPIView

上面我们看了mixin模块及generics模块的确节省了大量代码,可是还是存在重复代码,此时我们再来看下generics模块下的类们。

通过使用mixin类,我们使用更少的代码重写了这些视图,但我们还可以再进一步。REST框架提供了一组已经混合好(mixed-in)的通用视图,我们可以使用它来简化我们的views.py模块。

还是用author举例:

导入模块

from rest_framework import generics

views.py

class AuthorView(generics.ListCreateAPIView):    queryset = Author.objects.all()    serializer_class = AuthorModelSerializersclass AuthorDetailView(generics.RetrieveUpdateDestroyAPIView):    queryset = Author.objects.all()    serializer_class = AuthorModelSerializers

对比下看看

 

五、viewsets模块下的ModelViewSet

像上面所述,还是有重复代码,别急,还有更简便的。

记住核心在于,利用字典的形式指定请求方法(get、post...)的操作(list,create....)

导入模块

from rest_framework import viewsets

urls.py

urlpatterns = [    url(r'^admin/', admin.site.urls),    # url(r'^authors/$',views.AuthorView.as_view(),name='authors'),    # url(r'^authors/(?P
\d+)/$',views.AuthorDetailView.as_view(),name='author_detail'), url(r'^authors/$',views.AuthorModelView.as_view({
"get":"list","post":"create"}),name='authors'), url(r'^authors/(?P
\d+)/$',views.AuthorModelView.as_view({ 'get': 'retrieve', 'put': 'update', 'patch': 'partial_update', 'delete': 'destroy' }),name='author_detail'), url(r'^publishes/$',views.PublishView.as_view(),name='publishes'), url(r'^publishes/(?P
\d+)/$',views.PublishDetailView.as_view(),name='publish_detail'), url(r'^books/$',views.BookView.as_view(),name='books'), url(r'^books/(\d+)/$',views.BookDetailView.as_view(),name='book_detail'),]

views.py

from rest_framework import viewsetsclass AuthorModelView(viewsets.ModelViewSet):    queryset = Author.objects.all()    serializer_class = AuthorModelSerializers

如果你想用自己方法来处理请求,只需自己重写函数,并更改路由即可

转载于:https://www.cnblogs.com/neymargoal/p/9791004.html

你可能感兴趣的文章
使用 padding-bottom 设置高度基于宽度的自适应
查看>>
进程有一个全局变量i,还有有两个线程。i++在两个线程里边分别执行100次,能得到的最大值和最小值分别是多少?...
查看>>
DB2 数据库中字段特定字符替换为空
查看>>
解决VS2015启动界面卡在白屏的处理方法
查看>>
IIS下配置跨域设置Access-Control-Allow-Origin
查看>>
JS金字塔
查看>>
Ajax与JSON的一些总结
查看>>
C#常用控件属性及方法介绍
查看>>
51单片机寻址方式
查看>>
DB太大?一键帮你收缩所有DB文件大小(Shrink Files for All Databases in SQL Server)
查看>>
二叉树
查看>>
Leetcode: Convert Sorted Array to Binary Search Tree
查看>>
#python#类和实例绑定属性和方法的总结
查看>>
C#委托事件的理解猫与老鼠的故事
查看>>
TS4
查看>>
tomcat server.xml配置详解
查看>>
java05
查看>>
前后端通信 (3种方式简单介绍)
查看>>
java条件语句练习题
查看>>
文件操作open,r,w,a三种模式
查看>>