当前位置: 首页 > news >正文

北京华夏网站建设设计公司福州百度快速优化

北京华夏网站建设设计公司,福州百度快速优化,邢台网站建设公司,深圳室内设计培训前面介绍了什么是符合RESTful规范的API接口,以及使用了基于函数的视图(FBV)编写了对文章进行增删查改的API。在本篇文章将使用基于类的视图(Class-based View, CBV)重写之前的接口。 参考: 1、Django开发总结:Django MVT与MVC设计模式&…

前面介绍了什么是符合RESTful规范的API接口,以及使用了基于函数的视图(FBV)编写了对文章进行增删查改的API。在本篇文章将使用基于类的视图(Class-based View, CBV)重写之前的接口。

参考:

1、Django开发总结:Django MVT与MVC设计模式,请求过程与代码示例(附源码)_SteveRocket的博客-CSDN博客如果要开发一个好的网站或网络应用,就必需了解经典的软件开发所遵循的MVC 设计模式。本篇详细总结软件开发所遵循的MVC (Model-View-Controller, 模型-视图-控制器) 设计模式以及Django的MVT设计模式(Model-View-Template)如何遵循这种设计理念。Django Model(模型), URL(链接), View(视图) 和Template(模板)又是如何遵循MVC软件设计模式的。https://blog.csdn.net/zhouruifu2015/article/details/129648966

https://blog.csdn.net/zhouruifu2015/article/details/129761750icon-default.png?t=N2N8https://blog.csdn.net/zhouruifu2015/article/details/129761750

工程路径及APP:django_framework\django_rest_framework_pro\drf_pro

基于类的视图(CBV)

一个中大型的Web项目代码量通常是非常大的,如果全部使用函数视图写,那么代码的复用率是非常低的。而使用类视图,就可以有效的提高代码复用,因为类是可以被继承的,可以拓展的。特别是将一些可以共用的功能抽象成Mixin类或基类后可以减少重复造轮子的工作。

DRF推荐使用基于类的视图(CBV)来开发API, 并提供了4种开发CBV开发模式。

  • 使用基础APIView类
  • 使用Mixins类和GenericAPI类混配
  • 使用通用视图generics.*类, 比如generics.ListCreateAPIView
  • 使用视图集ViewSet和ModelViewSet

类视图的比较

DRF提供了4种编写CBV类API的方式,到底哪种CBV开发模式更好? 答案是各有利弊

  • 基础的API类可读性最高,代码最多,灵活性最高。当需要对API行为进行个性化定制时,建议使用这种方式。
  • 通用generics.*类可读性好,代码适中,灵活性较高。当需要对一个模型进行标准的增删查改全部或部分操作时建议使用这种方式。
  • 使用视图集viewset: 可读性较低,代码最少,灵活性最低。当需要对一个模型进行标准的增删查改的全部操作且不需定制API行为时建议使用这种方式。
  • mixin类和GenericAPI的混用,这个和generics.*类没什么区别,不看也罢。

Django视图集viewset代码最少,但这是以牺牲了代码的可读性为代价的,因为它对代码进行了高度地抽象化。另外urls由router生成,不如自己手动配置的清楚。

使用CBV类可以简化代码,增加代码重用,在很多情况下还需要重写父类的方法,比如get_queryset, get_serializer_class方法以实现特殊的功能。

使用APIView

DRF的APIView类继承了Django自带的View类, 一样可以按请求方法调用不同的处理函数,比如get方法处理GET请求,post方法处理POST请求。不过DRF的APIView要强大得多。它不仅支持更多请求方法,而且对Django的request对象进行了封装,可以使用request.data获取用户通过POST, PUT和PATCH方法发过来的数据,而且支持插拔式地配置认证、权限和限流类

使用APIView类重写之前的函数视图

# drf_pro/views.py

# 基础APIView类
from rest_framework import status
from rest_framework.views import APIView
from rest_framework.response import Response
from django.http import Http404
from .models import Article
from .serializers import ArticleSerializer2class ArticleList(APIView):"""List all articles, or create a new article."""def get(self, request, format=None):articles = Article.objects.all()serializer = ArticleSerializer2(articles, many=True)return Response(serializer.data)def post(self, request, format=None):serializer = ArticleSerializer2(data=request.data)if serializer.is_valid():# 注意:手动将request.user与author绑定serializer.save(author=request.user)return Response(serializer.data, status=status.HTTP_201_CREATED)return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)class ArticleDetail(APIView):"""Retrieve, update or delete an article instance."""def get_object(self, pk):try:return Article.objects.get(pk=pk)except Article.DoesNotExist:raise Http404def get(self, request, pk, format=None):article = self.get_object(pk)serializer = ArticleSerializer2(article)return Response(serializer.data)def put(self, request, pk, format=None):article = self.get_object(pk)serializer = ArticleSerializer2(instance=article, data=request.data)if serializer.is_valid():serializer.save()return Response(serializer.data)return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)def delete(self, request, pk, format=None):article = self.get_object(pk)article.delete()return Response(status=status.HTTP_204_NO_CONTENT)

或许已经注意到,这段代码跟之前基于函数的视图差别并不大。最大不同的是不需要在对用户的请求方法进行判断。该视图可以自动将不同请求转发到相应处理方法,逻辑上也更清晰。

修改url配置, 让其指向新的基于类的视图

# drf_pro/urls.py

from django.urls import re_path
from rest_framework.urlpatterns import format_suffix_patterns
from . import views, views_cbvurlpatterns = [re_path(r'^articles/$', views.article_list),re_path(r'^articles/(?P<pk>[0-9]+)$', views.article_detail),# 基于类的视图re_path(r'^articles_cbv/$', views_cbv.ArticleList.as_view()),# http://localhost/v1/articles_cbv/re_path(r'^articles_cbv/(?P<pk>[0-9]+)$', views_cbv.ArticleDetail.as_view()),
]urlpatterns = format_suffix_patterns(urlpatterns=urlpatterns)

发送GET请求到v1/articles_cbv/将看到跟上文一样的效果

发送GET请求到v1/articles_cbv/4/ 根据id查看详情

使用Mixin类和GenericAPI类混配

使用基础APIView类并没有大量简化代码,与增删改查操作相关的代码包括返回内容对所有模型几乎都是一样的。比如现在需要对文章类别Category模型也进行序列化和反序列化,只需要复制Article视图代码,将Article模型改成Category模型, 序列化类由ArticleSeralizer类改成CategorySerializer类就行了。

对于这些通用的增删改查行为,DRF已经提供了相应的Mixin类。Mixin类可与generics.GenericAPI类联用,灵活组合成所需要的视图。

使用Mixin类和generics.GenericAPI类重写的类视图

# drf_pro/views.py

# 使用Mixin类和generics.GenericAPI类重写的类视图
from rest_framework import mixins
from rest_framework import generics
class ArticleList2(mixins.ListModelMixin, mixins.CreateModelMixin, generics.GenericAPIView):"""GenericAPIView 类继承了APIView类,提供了基础的API视图。"""queryset = Article.objects.all()serializer_class = ArticleSerializer2def get(self, request, *args, **kwargs):return self.list(request, *args, **kwargs)def post(self, reqeust, *args, **kwargs):return self.create(reqeust, *args, **kwargs)

GenericAPIView 类继承了APIView类,提供了基础的API视图。它对用户请求进行了转发,并对Django自带的request对象进行了封装。不过它比APIView类更强大,因为它还可以通过queryset和serializer_class属性指定需要序列化与反序列化的模型或queryset及所用到的序列化器类。

这里的 ListModelMixin 和 CreateModelMixin类则分别引入了.list() 和 .create() 方法,当用户发送get请求时调用Mixin提供的list()方法,将指定queryset序列化后输出,发送post请求时调用Mixin提供的create()方法,创建新的实例对象。

DRF还提供RetrieveModelMixin, UpdateModelMixin和DestroyModelMixin类,实现了对单个对象实例的查、改和删操作,如下所示:

class ArticleDetail2(mixins.RetrieveModelMixin, mixins.UpdateModelMixin, mixins.DestroyModelMixin, generics.GenericAPIView):queryset = Article.objects.all()serializer_class = ArticleSerializer2def 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)

已经有了get, post, delete等方法,为什么mixin类引入的方法要以list, create, retrieve, destroy方法命名?

因为请求方法不如操作名字清晰,比如get方法同时对应了获取对象列表和单个对象两种操作,使用list和retrieve方法后则很容易区分。另外post方法接受用户发过来的请求数据后,有时只需转发不需要创建模型对象实例,所以post方法不能简单等于create方法。

新的ArticleList视图类看似正确,但其实还有一个问题。 定义的序列化器ArticleSeralizer类并不包含author这个字段的,这是因为希望在创建article实例时将author与request.user进行手动绑定。在前面的例子中使用serializer.save(author=request.user)这一方法进行手动绑定。

现在使用mixin类后的操作方法是重写perform_create方法,如下所示:

class ArticleList2(mixins.ListModelMixin, mixins.CreateModelMixin, generics.GenericAPIView):"""GenericAPIView 类继承了APIView类,提供了基础的API视图。"""queryset = Article.objects.all()serializer_class = ArticleSerializer2def get(self, request, *args, **kwargs):return self.list(request, *args, **kwargs)def post(self, reqeust, *args, **kwargs):return self.create(reqeust, *args, **kwargs)# 将request.user与author绑定def perform_create(self, serializer):serializer.save(author=self.request.user)

perform_create这个钩子函数是CreateModelMixin类自带的,用于执行创建对象时需要执行的其它方法,比如发送邮件等功能,有点类似于Django的信号。类似的钩子函数还有UpdateModelMixin提供的.perform_update方法和DestroyModelMixin提供的.perform_destroy方法。

urls.py中新定义URL

# 使用Mixin类和generics.GenericAPI类重写的类视图
re_path(r'^articles_cbv2/$', views_cbv.ArticleList2.as_view()),
re_path(r'^articles_cbv2/(?P<pk>[0-9]+)/$', views_cbv.ArticleDetail2.as_view()),

浏览器请求文章列表

浏览器请求单篇文章详情

使用通用视图generics.*

将Mixin类和GenericAPI类混配,已经帮助减少了一些代码,但还可以做得更好,比如将get请求与mixin提供的list方法进行绑定感觉有些多余。DRF还提供了一套常用的将 Mixin 类与 GenericAPI类已经组合好了的视图,开箱即用,可以进一步简化的代码,如下所示:

from rest_framework import generics
class ArticleList3(generics.ListCreateAPIView):queryset = Article.objects.all()serializer_class = ArticleSerializer2# 将request.user与author绑定def perform_create(self, serializer):serializer.save(author=self.request.user)class ArticleDetail3(generics.RetrieveUpdateAPIView):queryset = Article.objects.all()serializer_class = ArticleSerializer2

generics.ListCreateAPIView类支持List、Create两种视图功能,分别对应GET和POST请求。generics.RetrieveUpdateDestroyAPIView支持Retrieve、Update、Destroy操作,其对应方法分别是GET、PUT和DELETE。

urls.py中新定义URL

# generic class-based views
re_path(r'articles_cbv3/$', views_cbv.ArticleList3.as_view()),
re_path(r'articles_cbv3/(?P<pk>[0-9]+)/$', views_cbv.ArticleDetail3.as_view()),


短短几行代码实现了所有想要的功能,代码更简洁,其它常用generics.*类视图还包括ListAPIView, RetrieveAPIView, RetrieveUpdateAPIView等等。

使用视图集(viewset)

使用通用视图generics.*类后视图代码已经大大简化,但是ArticleList和ArticleDetail两个类中queryset和serializer_class属性依然存在代码重复。使用视图集可以将两个类视图进一步合并,一次性提供List、Create、Retrieve、Update、Destroy这5种常见操作,这样queryset和seralizer_class属性也只需定义一次就好, 如下所示:

# drf_pro/views.py

# 视图集(viewset)
from rest_framework import viewsets
class ArticleViewSet(viewsets.ModelViewSet):# 用一个视图集替代ArticleList和ArticleDetail两个视图queryset = Article.objects.all()serializer_class = ArticleSerializer2# 自行添加,将request.user与author绑定def perform_create(self, serializer):serializer.save(author = self.request.user)

使用视图集后,需要使用DRF提供的路由router来分发urls,因为一个视图集现在对应多个urls的组合,而不像之前的一个url对应一个视图函数或一个视图类。

# drf_pro/urls.py

# 使用视图集后,需要使用DRF提供的路由router来分发urls,因为一个视图集现在对应多个urls的组合
from rest_framework.routers import DefaultRouterrouter = DefaultRouter()
router.register(r'articles4', viewset=views_cbv.ArticleViewSet)
urlpatterns = [
]
urlpatterns += router.urls

 

浏览器访问

一个视图集对应List、Create、Retrieve、Update、Destroy这5种操作。有时候只需要其中的几种操作,该如何实现?答案是在urls.py中指定方法映射即可,如下所示:

# drf_pro/urls.py

from django.urls import re_path
from rest_framework.urlpatterns import format_suffix_patterns
from . import views, views_cbv# 针对只需要其中的几种操作 使用方法映射
article_list = views_cbv.ArticleViewSet.as_view({'get': 'list','post': 'create'
})
article_detail = views_cbv.ArticleViewSet.as_view({'get': 'retrieve'  # 只处理get请求,获取单个记录
})urlpatterns = [# 视图集(viewset)re_path(r'^articles5/$', article_list),re_path(r'^articles5/(?P<pk>[0-9]+)/$', article_detail),
]

 

另外DRF还提供了ReadOnlyModelViewSet这个类,仅支持list和retrive这个操作。

代码示例:https://download.csdn.net/download/zhouruifu2015/87611605

输入才有输出,吸收才能吐纳。——码字不易

http://www.mmbaike.com/news/62191.html

相关文章:

  • 整容网站模板成都网站推广
  • 亚马逊中国官方网站网页制作代码html制作一个网页
  • 国外做网站百度网址大全官网旧版
  • 黄骅市和渤海新区合并吗站长工具seo
  • 158百事通做网站是诈骗吗成都搜狗seo
  • 做网站app优惠活动的百度快照的作用是什么
  • 适合新手做的网站静态国际新闻最新消息今天
  • 文化类网站是不是休闲娱乐类网站广州优化防控措施
  • 做宣传图片的网站上海seo有哪些公司
  • 目前有做电子合同的网站吗东莞谷歌推广
  • 百合网网站建设与策划哪个平台可以免费发广告
  • 原油可以取什么做标题发网站南京最新消息今天
  • 口碑最好装修公司深圳关键词seo
  • 网站备案 时间网站的seo
  • 宝塔面板怎么做多个网站全国前十名小程序开发公司
  • 不会编程怎么做网站网络推广的方法
  • 成都网站设计 常凡云网络广告策划的步骤
  • 陕西省建设厅证件查询优化设计英语
  • 专门做特产的网站免费广告推广软件
  • 国内外做gif的网站北京网站定制公司
  • 做哪类英文网站赚钱seo培训学院
  • 网站用社交图标做链接侵权吗重庆网络推广平台
  • 网站首页下拉广告搜索引擎营销的常见方式
  • 网站如何做推广效果好seo网络优化是什么工作
  • 福州网站优化公司教育培训网
  • 乐清手机网站能够免费换友链的平台
  • 宁波怎么做网站排名优化百度数据库
  • 长春怎么做网站百度手机助手下载安装最新版
  • 中英双语网站源码数字营销软件
  • 2022加盟项目排行榜seo编辑招聘