一、视图层封装

二、ViewSetMixin

三、路由配置

四、解析器

五、响应器

一、视图层封装

  1.基本视图

    写一个出版社的增删改查resfull接口

    路由:

    url(r'^publish/$', views.PublishView.as_view()),
url(r'^publish/(?P<pk>\d+)/$', views.PublishDetailView.as_view()),

    视图:

class PublishSerializers(serializers.ModelSerializer):
class Meta:
model=models.Publish
fields='__all__' class PublishView(APIView): def get(self, request):
publish_list = models.Publish.objects.all()
bs = PublishSerializers(publish_list, many=True)
# 序列化数据 return Response(bs.data) def post(self, request):
# 添加一条数据
print(request.data) bs=PublishSerializers(data=request.data)
if bs.is_valid():
bs.save() # 生成记录
return Response(bs.data)
else: return Response(bs.errors) class PublishDetailView(APIView):
def get(self,request,pk):
publish_obj=models.Publish.objects.filter(pk=pk).first()
bs=PublishSerializers(publish_obj,many=False)
return Response(bs.data)
def put(self,request,pk):
publish_obj = models.Publish.objects.filter(pk=pk).first() bs=PublishSerializers(data=request.data,instance=publish_obj)
if bs.is_valid():
bs.save() # update
return Response(bs.data)
else:
return Response(bs.errors)
def delete(self,request,pk):
models.Publish.objects.filter(pk=pk).delete() return Response("")

  2.mixin类和generrice类编写视图

from rest_framework.mixins import CreateModelMixin,RetrieveModelMixin,ListModelMixin,UpdateModelMixin,DestroyModelMixin
from rest_framework.generics import GenericAPIView
class PublishView(ListModelMixin,CreateModelMixin,GenericAPIView):
queryset=models.Publish.objects.all()
serializer_class=PublishSerializers def get(self, request):
return self.list(request) def post(self, request):
return self.create(request) class PublishDetailView(RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin,GenericAPIView):
queryset=models.Publish.objects.all()
serializer_class=PublishSerializers
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)

  3.使用generics 下ListCreateAPIView,RetrieveUpdateDestroyAPIView

from rest_framework.generics import ListCreateAPIView,RetrieveUpdateDestroyAPIView
class PublishView(ListCreateAPIView):
queryset=models.Publish.objects.all()
serializer_class=PublishSerializers class PublishDetailView(RetrieveUpdateDestroyAPIView):
queryset=models.Publish.objects.all()
serializer_class=PublishSerializers

  4.使用ModeiViewSet

    路由:

url(r'^publish/$', views.PublishView.as_view({'get':'list','post':'create'})),
url(r'^publish/(?P<pk>\d+)/$', views.PublishView.as_view({'get':'retrieve','put':'update','delete':'destroy'})),

    视图:

from rest_framework.viewsets import ModelViewSet
class PublishView(ModelViewSet):
queryset=models.Publish.objects.all()
serializer_class=PublishSerializers

二、ViewSetMixin

-ViewSetMixin
# ViewSetMixin 写在前面,先找ViewSetMixin的as_view方法
# 用了ViewSetMixin ,视图类中,不需要再写get,post,delete....这些函数了,函数名可以自定义
# 而且这个视图类,可以响应多条路由 -使用:
-urls.py中
url(r'^publishs/', views.PublishView.as_view({'get': 'aaa','post':'ddd'})),
url(r'^bbb/', views.PublishView.as_view({'get': 'bbb','post':'ccc'})), -视图类中:
class PublishView(ViewSetMixin,APIView):
def aaa(self,request):
return Response({'status':100})
def bbb(self,request):
return Response({'bb': "bbb"})

三、路由控制器

  1.自定义路由(原生方式)

from django.conf.urls import url
from app01 import views
urlpatterns = [
url(r'^books/$', views.BookView.as_view()),
url(r'^books/(?P<pk>\d+)$', views.BookDetailView.as_view()),
]
class BookView(APIView):

    def get(self, request):
book_list = models.Book.objects.all()
bs = BookSerializers(book_list, many=True)
return Response(bs.data) def post(self, request):
# 添加一条数据
print(request.data) bs=BookSerializers(data=request.data)
if bs.is_valid():
bs.save() # 生成记录
return Response(bs.data)
else: return Response(bs.errors) class BookDetailView(APIView):
def get(self,request,pk):
book_obj=models.Book.objects.filter(pk=pk).first()
bs=BookSerializers(book_obj,many=False)
return Response(bs.data)
def put(self,request,pk):
book_obj = models.Book.objects.filter(pk=pk).first() bs=BookSerializers(data=request.data,instance=book_obj)
if bs.is_valid():
bs.save() # update
return Response(bs.data)
else:
return Response(bs.errors)
def delete(self,request,pk):
models.Book.objects.filter(pk=pk).delete() return Response(""

  2.半自动路由(视图类继承ModeViewSet)

from django.conf.urls import url
from app01 import views
urlpatterns = [
url(r'^publish/$', views.PublishView.as_view({'get':'list','post':'create'})),
url(r'^publish/(?P<pk>\d+)/$', views.PublishView.as_view({'get':'retrieve','put':'update','delete':'destroy'})), ]
from rest_framework.viewsets import ModelViewSet
class PublishView(ModelViewSet):
queryset=models.Publish.objects.all()
serializer_class=PublishSerializers

  3.全自动路由(自动生成路由)

from django.conf.urls import url,include
from app01 import views
from rest_framework import routers
router=routers.DefaultRouter()
# 两个参数,一个是匹配的路由,一个是视图中写的CBV的类
router.register('publish',views.PublishView)
urlpatterns = [
# http://127.0.0.1:8000/publish/format=json(渲染器通过这个判断,返回渲染的页面)
# url(r'^publish/', views.PublishView.as_view({'get':'list','post':'create'})),
# http://127.0.0.1:8000/publish.json(渲染器通过这个判断,返回渲染的页面)
# url(r'^publish\.(?P<format>\w+)$', views.PublishView.as_view({'get':'list','post':'create'})), # 可以用 以下方式访问
# 1 http://127.0.0.1:8000/publish/
# 2 http://127.0.0.1:8000/publish.json
# 3 http://127.0.0.1:8000/publish/3
# 4 http://127.0.0.1:8000/publish/3.json
url(r'',include(router.urls))
]
from rest_framework.viewsets import ModelViewSet
class PublishView(ModelViewSet):
queryset=models.Publish.objects.all()
serializer_class=PublishSerializers
# 小结:
-传统的url配置
url(r'^books/$', views.BookView.as_view()),
url(r'^books/(?P<pk>\d+)$', views.BookDetailView.as_view()),
-半自动
url(r'^publish/$', views.PublishView.as_view({'get':'list','post':'create'})),
url(r'^publish/(?P<pk>\d+)/$', views.PublishView.as_view({'get':'retrieve','put':'update','delete':'destroy'})),
-全自动(了解)
-能自动生成多条路由

四、解析器

  1.解析器的作用

    根据请求头content-type选择对应的解析器队请求体内容进行处理

    有appliction/json,x-www-form-urlencoded,form-data等格式

  2.全局使用解析器

    setting里

REST_FRAMEWORK = {
'DEFAULT_PARSER_CLASSES':[
'rest_framework.parsers.JSONParser'
'rest_framework.parsers.FormParser'
'rest_framework.parsers.MultiPartParser'
] }

    路由:

urlpatterns = [
url(r'test/', TestView.as_view()),
]

    视图函数:

from rest_framework.views import APIView
from rest_framework.response import Response class TestView(APIView):
def post(self, request, *args, **kwargs):
print(request.content_type) # 获取请求的值,并使用对应的JSONParser进行处理
print(request.data)
# application/x-www-form-urlencoded 或 multipart/form-data时,request.POST中才有值
print(request.POST)
print(request.FILES)
return Response('POST请求,响应内容') def put(self, request, *args, **kwargs):
return Response('PUT请求,响应内容')

  3.局部使用解析器

a.仅处理请求头content-type为appliction/json请求体

from django.conf.urls import url, include
from web.views.s5_parser import TestView urlpatterns = [
url(r'test/', TestView.as_view(), name='test'),
]
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.request import Request
from rest_framework.parsers import JSONParser class TestView(APIView):
parser_classes = [JSONParser, ] def post(self, request, *args, **kwargs):
print(request.content_type) # 获取请求的值,并使用对应的JSONParser进行处理
print(request.data) # application/x-www-form-urlencoded 或 multipart/form-data时,request.POST中才有值
print(request.POST)
print(request.FILES) return Response('POST请求,响应内容') def put(self, request, *args, **kwargs):
return Response('PUT请求,响应内容')

b.仅处理请求头content-type为appliction/x-www-from-urlencoded的请求体

from django.conf.urls import url, include
from web.views import TestView urlpatterns = [
url(r'test/', TestView.as_view(), name='test'),
]
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.request import Request
from rest_framework.parsers import FormParser class TestView(APIView):
parser_classes = [FormParser, ] def post(self, request, *args, **kwargs):
print(request.content_type) # 获取请求的值,并使用对应的JSONParser进行处理
print(request.data) # application/x-www-form-urlencoded 或 multipart/form-data时,request.POST中才有值
print(request.POST)
print(request.FILES) return Response('POST请求,响应内容') def put(self, request, *args, **kwargs):
return Response('PUT请求,响应内容')

c.仅仅处理请求头content-type为multipart/form-data的请求体

from django.conf.urls import url, include
from web.views import TestView urlpatterns = [
url(r'test/', TestView.as_view(), name='test'),
]
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.request import Request
from rest_framework.parsers import MultiPartParser class TestView(APIView):
parser_classes = [MultiPartParser, ] def post(self, request, *args, **kwargs):
print(request.content_type) # 获取请求的值,并使用对应的JSONParser进行处理
print(request.data)
# application/x-www-form-urlencoded 或 multipart/form-data时,request.POST中才有值
print(request.POST)
print(request.FILES)
return Response('POST请求,响应内容') def put(self, request, *args, **kwargs):
return Response('PUT请求,响应内容')
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="http://127.0.0.1:8000/test/" method="post" enctype="multipart/form-data">
<input type="text" name="user" />
<input type="file" name="img"> <input type="submit" value="提交"> </form>
</body>
</html>

d.仅上传文件

from django.conf.urls import url, include
from web.views import TestView urlpatterns = [
url(r'test/(?P<filename>[^/]+)', TestView.as_view(), name='test'),
]
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.request import Request
from rest_framework.parsers import FileUploadParser class TestView(APIView):
parser_classes = [FileUploadParser, ] def post(self, request, filename, *args, **kwargs):
print(filename)
print(request.content_type) # 获取请求的值,并使用对应的JSONParser进行处理
print(request.data)
# application/x-www-form-urlencoded 或 multipart/form-data时,request.POST中才有值
print(request.POST)
print(request.FILES)
return Response('POST请求,响应内容') def put(self, request, *args, **kwargs):
return Response('PUT请求,响应内容')
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="http://127.0.0.1:8000/test/f1.numbers" method="post" enctype="multipart/form-data">
<input type="text" name="user" />
<input type="file" name="img"> <input type="submit" value="提交"> </form>
</body>
</html>

e.同时多个Parser

当同时使用多个parser时,rest_framework会根据请求头content-type自动进行比对,并使用对应parser

from django.conf.urls import url, include
from web.views import TestView urlpatterns = [
url(r'test/', TestView.as_view(), name='test'),
]
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.request import Request
from rest_framework.parsers import JSONParser, FormParser, MultiPartParser class TestView(APIView):
parser_classes = [JSONParser, FormParser, MultiPartParser, ] def post(self, request, *args, **kwargs):
print(request.content_type) # 获取请求的值,并使用对应的JSONParser进行处理
print(request.data)
# application/x-www-form-urlencoded 或 multipart/form-data时,request.POST中才有值
print(request.POST)
print(request.FILES)
return Response('POST请求,响应内容') def put(self, request, *args, **kwargs):
return Response('PUT请求,响应内容')

  4.源码分析

1 在调用request.data时,才进行解析,由此入手
@property
def data(self):
if not _hasattr(self, '_full_data'):
self._load_data_and_files()
return self._full_data 2 查看self._load_data_and_files()方法---->self._data, self._files = self._parse() def _parse(self):
#用户请求头里content_type的值
media_type = self.content_type #self.parsers 就是用户配置的parser_classes = [FileUploadParser,FormParser ]
#self里就有content_type,传入此函数
parser = self.negotiator.select_parser(self, self.parsers) 3 查看self.negotiator.select_parser(self, self.parsers)
def select_parser(self, request, parsers):
#同过media_type和request.content_type比较,来返回解析器,然后调用解析器的解析方法
#每个解析器都有media_type = 'multipart/form-data'属性
for parser in parsers:
if media_type_matches(parser.media_type, request.content_type):
return parser
return None 4 最终调用parser的解析方法来解析parsed = parser.parse(stream, media_type, self.parser_context)
1 Request实例化,parsers=self.get_parsers()
Request(
request,
parsers=self.get_parsers(),
authenticators=self.get_authenticators(),
negotiator=self.get_content_negotiator(),
parser_context=parser_context
)
2 get_parsers方法,循环实例化出self.parser_classes中类对象
def get_parsers(self):
return [parser() for parser in self.parser_classes] 3 self.parser_classes 先从类本身找,找不到去父类找即APIVIew 中的
parser_classes = api_settings.DEFAULT_PARSER_CLASSES
4 api_settings是一个对象,对象里找DEFAULT_PARSER_CLASSES属性,找不到,会到getattr方法
def __getattr__(self, attr):
if attr not in self.defaults:
raise AttributeError("Invalid API setting: '%s'" % attr) try:
#调用self.user_settings方法,返回一个字典,字典再取attr属性
val = self.user_settings[attr]
except KeyError:
# Fall back to defaults
val = self.defaults[attr] # Coerce import strings into classes
if attr in self.import_strings:
val = perform_import(val, attr) # Cache the result
self._cached_attrs.add(attr)
setattr(self, attr, val)
return val
5 user_settings方法 ,通过反射去setting配置文件里找REST_FRAMEWORK属性,找不到,返回空字典
@property
def user_settings(self):
if not hasattr(self, '_user_settings'):
self._user_settings = getattr(settings, 'REST_FRAMEWORK', {})
return self._user_settings

五、响应器

  1.作用

    根据用户请求url或用户可接受的类型,筛选出合适的渲染组件

    用户请求URL:

      http://127.0.0.1:8000/test/?format=json
           http://127.0.0.1:8000/test.json

  

  2.内置渲染器  

显示json格式:JSONRenderer

访问URL:

  • http://127.0.0.1:8000/test/?format=json
  • http://127.0.0.1:8000/test.json
  • http://127.0.0.1:8000/test/
     

默认显示格式:BrowsableAPIRenderer(可以修改它的html文件)

访问URL:

  • http://127.0.0.1:8000/test/?format=api
  • http://127.0.0.1:8000/test.api
  • http://127.0.0.1:8000/test/

表格方式:AdminRenderer

访问URL:

  • http://127.0.0.1:8000/test/?format=admin
  • http://127.0.0.1:8000/test.admin
  • http://127.0.0.1:8000/test/

form表单方式:HTMLFormRenderer

访问URL:

  • http://127.0.0.1:8000/test/?format=form
  • http://127.0.0.1:8000/test.form
  • http://127.0.0.1:8000/test/

  3.局部使用

from rest_framework.renderers import  HTMLFormRenderer,BrowsableAPIRenderer
class BookDetailView(APIView):
renderer_classes = [HTMLFormRenderer,BrowsableAPIRenderer ]
def get(self,request,pk):
book_obj=models.Book.objects.filter(pk=pk).first()
bs=BookSerializers(book_obj,many=False)
return Response(bs.data)
def put(self,request,pk):
book_obj = models.Book.objects.filter(pk=pk).first() bs=BookSerializers(data=request.data,instance=book_obj)
if bs.is_valid():
bs.save() # update
return Response(bs.data)
else:
return Response(bs.errors)
def delete(self,request,pk):
models.Book.objects.filter(pk=pk).delete() return Response("")

  4.全局使用

    setting里配置:

REST_FRAMEWORK = {
'DEFAULT_RENDERER_CLASSES':['rest_framework.renderers.JSONRenderer']
}

  5.自定义显示模板

from rest_framework.renderers import  TemplateHTMLRenderer
class BookDetailView(APIView):
renderer_classes = [TemplateHTMLRenderer]
def get(self,request,pk):
book_obj=models.Book.objects.filter(pk=pk).first()
bs=BookSerializers(book_obj,many=False)
return Response(bs.data,template_name='aa.html')
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
{{ title }}
{{ publishDate }}
</body>
</html>

Django drf:视图层封装、ViewSetMixin、路由配置、解析器、响应器的更多相关文章

  1. Django的视图层简介

    Django的视图层 视图函数 所谓视图函数,其实就是我们Django项目中各个应用中的views.py文件中定义的每个用来处理URL路由映射到这里的逻辑函数.一个视图函数简称视图,它是个简单的Pyt ...

  2. Mybatis源码解析,一步一步从浅入深(三):实例化xml配置解析器(XMLConfigBuilder)

    在上一篇文章:Mybatis源码解析,一步一步从浅入深(二):按步骤解析源码 ,中我们看到 代码:XMLConfigBuilder parser = new XMLConfigBuilder(read ...

  3. configparser_配置解析器

    configparser:配置解析器 import configparser config = configparser.ConfigParser() #配置文件 config[', 'Compres ...

  4. Django-1版本的路由层、Django的视图层和模板层

    一.Django-1版本的路由层(URLconf) URL配置(URLconf)就像Django所支撑网站的目录.它的本质是URL与要为该URL调用的视图函数之间的映射表:我们就是以这种方式告诉Dja ...

  5. django之视图层和部分模板层

    视图层 小白必会三板斧(三个返回的都是HttpResponse对象,通过看源码,可以知道是内部实现) 1.HttpResponse # 返回字符串 2.render # 返回一个html页面 还可以给 ...

  6. 【Django】 视图层说明

    [Django视图层] 视图层的主要工作是衔接HTTP请求,Python程序和HTML模板,使他们能够有机互相合作从模型层lou到数据并且反馈.说到视图层的工作就有以下几个方面要说 ■ URL映射 对 ...

  7. Django之视图层与模板层

    目录 视图层 小白必会三板斧 HttpResponse render redirect JsonResponse 前后端分离 FBV CBV 给CBV加装饰器 模板层 模板语法 模板传值 过滤器 语法 ...

  8. django 之视图层及模板层 04

    目录 视图层 render方法是Template和Contex两个对象的组合使用 JsonResponse对象 CBV及源码分析 CBV 加装饰器的方式 模板层 模板语法传值 模板语法 变量 过滤器( ...

  9. drf 解析器,响应器,路由控制

    解析器 作用: 根据请求头 content-type 选择对应的解析器对请求体内容进行处理. 有application/json,x-www-form-urlencoded,form-data等格式 ...

随机推荐

  1. 【Leetcode_easy】700. Search in a Binary Search Tree

    problem 700. Search in a Binary Search Tree 参考1. Leetcode_easy_700. Search in a Binary Search Tree; ...

  2. Nginx作为负载均衡把客户端真实IP发送给后端配置

    Nginx作为负载均衡获取到客户端的真实IP,但是后端获取到的IP为nginx负载均衡的IP,需要修改配置使后端获取到客户端的真实IP 修改nginx配置增加3行 proxy_set_header H ...

  3. idea的enable auto-import/内存设置

    设置pom.xml依赖的自动导入 设置idea的memory heap On the Help menu, click Edit Custom VM Options. Set the -Xmx opt ...

  4. sqlserver 数据库操作导出数据sql工具

    软件名称sqldbx 下载URL  https://download.csdn.net/download/yanghl1998/7832861 Navicat Premium  这个工具任何类型数据库 ...

  5. 【C# 开发技巧】番外篇故事-我是一个线程

    我是一个线程 我是一个线程,一出生就被编了一个号——0x3704,然后被领到一间昏暗的屋子里,在这里,我发现了很多和我一模一样的同伴.我身边的同伴0x6900待的时间比较长,他带着沧桑的口气对我说:“ ...

  6. Net中实现HTML生成图片或PDF

    Net中实现HTML生成图片或PDF的几种方式 前段时间由于项目上的需求,要在.Net平台下实现把HTML内容生成图片或PDF文件的功能,特意在网上研究了几种方案,这里记录一下以备日后再次使用.当时想 ...

  7. [学习笔记] Blender 常用工具栏,选择及游标

    Shift + A 创建物体 选择工具: 默认是框选 shift 鼠标左键 加选, 再次可减选 游标 默认情况下游标在世界中心.创建新物体时,会自动被创建在游标的位置.可以随意改变游标的位置,便于建模 ...

  8. EMR目录

    EMR目录: E-MapReduce 是阿里云上的开源大数据平台,用户可以登录集群主节点查看相关安装路径. 登录后也可以使用 env |grep xxx 查看. 或者,在EMR Hadoop集群,切换 ...

  9. 2个CDH的hive数据同步

    算法和数仓共用一套hive数据: CM: 真实数据: 都存在共享存储: oss, s3,ufile上. CDH配置能访问的权限(key)

  10. 对快速排序的理解以及相关c++代码

    快速排序:在一组数据中,可以将左边的数字当作枢轴(右边也可以),接下来要做的就是,先从右边找到比枢轴小的数, 再从左边找到比枢轴大的数,接着将这两个数进行交换,重复上述步骤找出所有符合条件的数进行交换 ...