1.drf框架知识点概况
2.接口概念
3.resful接口规范
4.原生django实现接口准备
5.CBV请求生命周期源码回顾
6.原生django单查群差接口
7.Postman接口请求工具
8.原生django单增接口
9.drf安装与封装风格
10.drf请求的生命周期
11.请求模块
12.渲染模块
一.drf框架知识点概况(所有知识点)
drf框架全称:django-rest framework
1.接口:什么是接口,restful接口规范 2.CBV生命周期源码 - 基于restful规范下的CBV接口 3.请求组件,解析组件,响应组件 4.序列化组件 (灵魂) 5.三大认证(重中之重):认证,权限(权限六表),频率 6.其他组件:过滤,筛选,排序,分页,路由 还有一个比较难的点:源码分析
二.接口概念
接口:联系俩个物质的媒介,完成信息交互
web程序中:联系前台页面与后台数据库的媒介
web接口组成:
url:长得像返回数据的url连接
请求参数:前台按照指定的key提供数据给后台
响应数据:后台与数据库交互后将数据反馈给前台
三.resful接口规范
接口规范:就是为了采用不同的后台语言,也能使用同样的接口获取到同样的数据。
如何写接口:接口规范是规范化书写接口的,写接口要写url,响应数据
ps:如果将请求参数也纳入考量范围,那就是在写接口文档
俩大部分:url 响应数据
第一部分:url
1. 用api关键字标识接口url api.baidu.com | www.baidu.com/api 2. 接口数据安全性决定优先选择https协议 3. 如果一个接口有多版本存在,需要在url中标识体现 api.baidu.com/v1/... | api.baidu.com/v2/... 4. 接口操作的数据源称之为资源,在url中一般采用资源复数形式,一个接口可以概括对该资源的多种操作方式 api.baidu.com/books | api.baidu.com/books/(pk) 5. 请求方式有多种,用一个url处理如何保证不混乱 - 通过请求方式标识操作资源的方式 /books get 获取所有 /books get 增加一个(多个) /books/(pk) delete 删除一个 /books/(pk) put 整体更新一个 /books/(pk) patch 局部更新一个 6. 资源往往涉及数据的各种操作方式 - 筛选,排序,限制
api.baidu.com/books/?search=西&ordering=-price&limit=3响应数据
第二部分:响应数据
1. http请求的响应会有响应状态码,接口用来返回操作的资源数据,可以拥有 操作数据结果的 状态码 status 0(操作资源成功) 1(操作资源失败) 2(操作资源成功,但没匹配结果) 注:资源状态码不像http状态码,一般都是后台与前台或是客户约定的 2. 资源的状态码文字提示 status ok '账号有误' '密码有误' '用户锁定' 3. 资源本身 results ps:删除资源成功不做任何数据返回(返回空字符串) 但是一般开发项目的时候,我们是不遵守这一规定的,还是要返回一个标识来表明资源已删除 4. 不能直接返回的资源(子资源,图片,视频等资源),返回该资源的url链接
四.原生django实现接口准备
主路由:url.py
# 路由分发先导入include from django.conf.urls import url,include from django.contrib import admin urlpatterns = [ url(r'^admin/', admin.site.urls), # 路由分发 url(r'^api/', include('api.urls')), ]
api组件的子路由:api/url.py
from django.conf.urls import url from . import views # 子路由 urlpatterns = [ # 获取多个 url(r'^books/$',views.Book.as_view()), # 获取一个 url(r'^books/(?P.*)/$ ',views.Book.as_view()), ]
模型层:model.py
from django.db import models # 创建模型表 class Book(models.Model): title = models.CharField(max_length=64) # 这样写就不用考虑数字精度了 price = models.DecimalField(max_digits=5,decimal_places=2) # 就是修改django admin后台的一些显示 class Meta: db_table = 'old_boy_book' # 修改表名 verbose_name = '书籍' # 改为中文 verbose_name_plural = verbose_name # 不写的话,admin后台数据书籍后面会加个s def __str__(self): return '<%s>'%self.title
后台层:admin.py
from django.contrib import admin from . import models # 把你的表注册到admin admin.site.register(models.Book)
数据库迁移:
>: python manage.py makemigrations >: python manage.py migrrate 创建超级用户:只有超级用户才能登陆admin后台 >: python manage.py createsuperuser
视图层:views.py (核心代码) 原生django单查群差接口 原生django单增接口
![](http://img.e-com-net.com/image/info8/2b246dbcfe82488397e9aa432bbc4e31.gif)
1 from django.http import JsonResponse 2 from django.views import View 3 from . import models 4 5 6 # 六大基础接口:获取一个,获取所有,增加一个,删除一个,整体更新一个,局部更新一个 7 # 十大接口:群增,群删,整体改群该,局部改群该 8 class Book(View): 9 def get(self, request, *args, **kwargs): 10 # 这里要指定一下safe=False,因为默认为True,为True就要返回一个字典 11 pk = kwargs.get('pk') 12 if not pk: # 群查 13 book_obj_list = models.Book.objects.all() 14 book_list = [] 15 for obj in book_obj_list: 16 dic = {} 17 # 就是把对象转化为字典,然后把同等的数据转化为数组 18 dic['title'] = obj.title 19 dic['price'] = obj.price 20 book_list.append(dic) 21 return JsonResponse({ 22 'status': 0, 23 'msg': 'ok', 24 'results': book_list # 携带的是资源 25 # 返回的数据显示中文 26 }, json_dumps_params={'ensure_ascii': False}) 27 else: # 单查 28 # values 拿到的是字典 first拿到的是对象 这个是包含了多个字典的数组,需要点first 29 book_dic = models.Book.objects.filter(pk=pk).values('title', 'price').first() 30 if book_dic: 31 return JsonResponse({ 32 'status': 0, 33 'msg': 'ok', 34 'results': book_dic 35 }, json_dumps_params={'ensure_ascii': False}) 36 return JsonResponse({ 37 'status': 2, 38 'msg': '无结果', 39 }, json_dumps_params={'ensure_ascii': False}) 40 41 # 现在浏览器无法发送post请求,需要借助一个postman这个工具 42 # postman可以完成不同方式的请求:get | post | put ... 43 # postman发送数据包有三种方式:form-data | urlencoding | json 44 # 原生django对urlencoding方式数据兼容最好(所以一般都用这个) 45 def post(self, request, *args, **kwargs): 46 # 前台通过urlencoding方式提交数据 47 # 新增数据 拿到的值是关键字参数,需要打散解压赋值 48 # 因为如果我发送的数据不准确,就会报错,需要try一下 49 try: # 点dic就是把数据转换为字典的形式 50 book_obj = models.Book.objects.create(**request.POST.dict()) 51 if book_obj: 52 return JsonResponse({ 53 'status': 0, 54 'msg': 'ok', 55 'results': {'title': book_obj.title, 'price': book_obj.price} 56 }, json_dumps_params={'ensure_ascii': False}) 57 except: 58 return JsonResponse({ 59 'status': 1, 60 'msg': '参数有误', 61 }, json_dumps_params={'ensure_ascii': False}) 62 63 return JsonResponse({ 64 'status': 2, 65 'msg': '新增失败', 66 }, json_dumps_params={'ensure_ascii': False})
五.Postman接口请求工具
官网下载安装 get请求,携带参数采用Params post等请求,提交数据包可以采用三种方式:form-date、urlencoding、json 如果发送文件就用:form-date ,键值对数据就用:urlencoding ,json数据就用:json 所有请求都可以携带请求头
六.drf安装与封装风格
如何安装drf框架,可以在pycharm里面的中端:
>: pip3 install djangorestframework
drf框架的封装风格(非常的规矩)
from rest_framework.views import APIView from rest_framework.response import Response 响应数据的 from rest_framework.request import Request 请求数据的 from rest_framework.serializers import Serializer 序列化 from rest_framework.settings import APISettings 设置 from rest_framework.filters import SearchFilter 过虑器 from rest_framework.pagination import PageNumberPagination 分页 from rest_framework.authentication import TokenAuthentication 认证 from rest_framework.permissions import IsAuthenticated 是否是登录用户 from rest_framework.throttling import SimpleRateThrottle 频率 class Test(APIView): def get(self, request, *args, **kwargs): return Response('drf get ok')
from rest_framework.views import APIView from rest_framework.response import Response 响应数据的 from rest_framework.request import Request 请求数据的 from rest_framework.serializers import Serializer 序列化 from rest_framework.settings import APISettings 设置 from rest_framework.filters import SearchFilter 过虑器 from rest_framework.pagination import PageNumberPagination 分页 from rest_framework.authentication import TokenAuthentication 认证 from rest_framework.permissions import IsAuthenticated 是否是登录用户 from rest_framework.throttling import SimpleRateThrottle 频率 class Test(APIView): def get(self, request, *args, **kwargs): return Response('drf get ok')
七.drf请求的生命周期
""" 1) 请求走的是APIView的as_view函数 2) 在APIView的as_view调用父类(django原生)的as_view,还禁用了 csrf 认证 3) 在父类的as_view中dispatch方法请求走的又是APIView的dispatch 4) 完成任务方法交给视图类的请求函数处理,得到请求的响应结果,返回给前台 """
八.请求模块:request对象
源码入口
APIView类的dispatch方法中:request = self.initialize_request(request, *args, **kwargs)
源码分析:
""" # 二次封装得到def的request对象 request = self.initialize_request(request, *args, **kwargs) 点进去 # 在rest_framework.request.Request实例化方法中 self._request = request 将原生request作为新request的_request属性 # 在rest_framework.request.Request的__getattr__方法中 try: return getattr(self._request, attr) # 访问属性完全兼容原生request except AttributeError: return self.__getattribute__(attr) """
重点总结:
# 1) drf 对原生request做了二次封装,request._request就是原生request # 2) 原生request对象的属性和方法都可以被drf的request对象直接访问(兼容) # 3) drf请求的所有url拼接参数均被解析到query_params中,所有数据包数据都被解析到data中
代码:
class Test(APIView): def get(self, request, *args, **kwargs): # url拼接的参数 print(request._request.GET) # 二次封装方式 print(request.GET) # 兼容 print(request.query_params) # 拓展 return Response('drf get ok') def post(self, request, *args, **kwargs): # 所有请求方式携带的数据包 print(request._request.POST) # 二次封装方式 print(request.POST) # 兼容 print(request.data) # 拓展,兼容性最强,三种数据方式都可以 print(request.query_params) return Response('drf post ok')
九.渲染模块(浏览器和Postman请求结果渲染数据的方式不一样)
源码入口:
APIView类的dispatch方法中:self.response = self.finalize_response(request, response, *args, **kwargs)
源码分析:
""" # 最后解析reponse对象数据 self.response = self.finalize_response(request, response, *args, **kwargs) 点进去 # 拿到运行的解析类的对象们 neg = self.perform_content_negotiation(request, force=True) 点进去 # 获得解析类对象 renderers = self.get_renderers() 点进去 # 从视图类中得到renderer_classes请求类,如何实例化一个个对象形参解析类对象列表 return [renderer() for renderer in self.renderer_classes] 重点************************* # 重点:self.renderer_classes获取renderer_classes的顺序 # 自己视图类的类属性(局部配置) => # APIView类的类属性设置 => # 自己配置文件的DEFAULT_RENDERER_CLASSES(全局配置) => # drf配置文件的DEFAULT_RENDERER_CLASSES """
全局配置:所有视图类统一处理,在项目的settings.py中
REST_FRAMEWORK = { # drf提供的渲染类 'DEFAULT_RENDERER_CLASSES': [ 'rest_framework.renderers.JSONRenderer', 'rest_framework.renderers.BrowsableAPIRenderer', ], }
局部配置:某一个或一些实体类单独处理,在views.py视图类中提供对应的类属性
class Test(APIView): def get(self, request, *args, **kwargs): return Response('drf get ok') def post(self, request, *args, **kwargs): return Response('drf post ok') # 在setting.py中配置REST_FRAMEWORK,完成的是全局配置,所有接口统一处理 # 如果只有部分接口特殊化,可以完成 - 局部配置 from rest_framework.renderers import JSONRenderer class Test2(APIView): # 局部配置 renderer_classes = [JSONRenderer] def get(self, request, *args, **kwargs): return Response('drf get ok 2') def post(self, request, *args, **kwargs): return Response('drf post ok 2')