drf 基础
1.接口:什么 是接口 restful接口规范
2、CBV生命周期源码 - 基于restful规范下的CBV接口
3、请求组件、解析组件、响应组件
4、序列化组件(灵魂)
5、三大认证(重中之重):认证、权限(权限六表)、频率
6、其他组件:过滤、筛选、排序、分页、路由
''' 接口:联系两个物质的媒介,完成信息交互 web程序中:联系前台页面与后台数据库的媒介 web接口组成: url:长的像返回数据的url链接 请求参数:前台按照指定的key提供数据给后台 响应数据:后台与数据库交互后将数据反馈给前台 '''
接口规范:就是为了采用不同的后台语言,也能使用同样的接口获取到同样的数据 如何写接口:接口规范是 规范化书写接口的,写接口要写 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 获取所有
下面的四个完全兼容get请求
/books post 增加一个(多个)
/books/(pk) delete 删除一个
/books/(pk) put 整体更新一个
/books/(pk) patch 局部更新一个
/books post 增加一个(多个)
/books/(pk) delete 删除一个
/books/(pk) put 整体更新一个
/books/(pk) patch 局部更新一个
6) 资源往往涉及数据的各种操作方式 - 筛选、排序、限制
api.baidu.com/books/?search=西&ordering=-price&limit=3
api.baidu.com/books/?search=西&ordering=-price&limit=3
响应方式: 1) http请求的响应会有响应状态码,接口用来返回操作的资源数据,可以拥有 操作数据结果的 状态码 status 0(操作资源成功) 1(操作资源失败) 2(操作资源成功,但没匹配结果) 注:资源状态码不像http状态码,一般都是后台与前台或是客户约定的
数据状态码: 例如:status 0(操作资源成功)
数据提示: 例如: msg:登录失败
资源本身:要返回的资源
2) 资源的状态码文字提示 status ok '账号有误' '密码有误' '用户锁定' 3) 资源本身 results 注:删除资源成功不做任何数据返回(返回空字符串) 4) 不能直接返回的资源(子资源、图片、视频等资源),返回该资源的url链接 总结:接口由两部分组成:url(其实就是一个接口),响应数据.请求数据 url: 1,首相遵循restful接口规范协议 2,在url前要加上https:决定接口数据的安全性(头) 3,用api关键字标识接口url 4,接口操作资源(数据),通常以复数显示,里面包括对该资源的多种操作方式(get,post,delete,put,patch) 响应数据: 1,status,资源状态码 2,资源的状态码文本提示: 3,资源本身:即要返回给前端的数据 ps:不能直接返回的资源有图片,视频,子资源 通过请求方式(get|post|update|patch|delete)来操作资源,还有在url中可以对数据进行限制 ,排序等等 通过发送请求,可以拿到后台按照规范的响应数据,数据是一个超大的{} 资源状态码 资源的状态码文本提示 result资源本身 案列{ 'status':0, 'msg':'ok', 'result':[{ 'title':*, 'price':*, 'img':https://* }]
主路由:url.py 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<pk>.*)/$', 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) class Meta: db_table = 'old_boy_book' verbose_name = '书籍' verbose_name_plural = verbose_name def __str__(self): return '《%s》' % self.title
from django.contrib import admin from . import models admin.site.register(models.Book)
>: python manage.py makemigrations >: python manage.py migrrate >: python manage.py createsuperuser
视图层:views.py
from django.http import JsonResponse # Create your views here. from django.views import View from . import models class Book(View): def get(self,request,*args,**kwargs): # 路由分发,有名分组即关键字传参 pk = kwargs.get('pk') if not pk: # 群查 # 从数据库中获取数据 book_list_obj = models.Book.objects.all() # 序列化过程 book_list = [] for obj in book_list_obj: print(obj) # 把数据转化为字典格式,解压赋值 dic = {} dic['title'] = obj.title dic['price'] = obj.price book_list.append(dic) #返回 响应数据 return JsonResponse({ 'status':0, 'msg':'ok', 'result':book_list # 后端处理后的数据 },json_dumps_params={'ensure_ascii':False}) # 转换为前端识别的json格式 else: # 单查 book_dic = models.Book.objects.filter(pk=pk).values('title','price').first() if book_dic: return JsonResponse({ 'status':0, 'msg':'ok', 'result':book_dic, },json_dumps_params={'ensure_ascii':False}) return JsonResponse({ 'status': 2, 'msg': '无结果', }, json_dumps_params={'ensure_ascii': False}) # postman 可以完成不同方式的请求:get|post|put.... # postman 发送数据包的方式有三种:form-data|urlencoding|json # 原生django对urlencoding方式数据兼容最好 def post(self,request,*args,**kwargs): print(request.POST) #<QueryDict: {'title': ['三国演义'], 'price': ['2.99']}> print(request.body) res = request.POST print(res.dict()) # 前台通过urlencoding方式提交数据 try: # **request.POST.dict() 打散,request拥有dict方法 book_obj = models.Book.objects.create(**request.POST.dict()) if book_obj: return JsonResponse({ 'status':0, 'msg':'ok', # 获取前端数据,把真实数据字典赋值 'result':{'title': book_obj.title,'price':book_obj.price} },json_dumps_params={'ensure_ascii':False}) except: return JsonResponse({ 'status':1, 'msg':'数据有误', },json_dumps_params={'ensure_ascii':False}) return JsonResponse({ 'status':2, 'msg':'增加失败', },json_dumps_params={'ensure_ascii':False})
官网下载安装
get请求,携带参数采用Params
post等请求,提交数据包可以采用三种方式:form-date、urlencoding、json
所有请求都可以携带请求头
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'api.apps.ApiConfig', # 在这里进行注册 'rest_framework',]
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')
1) 请求走的是APIView的as_view函数
2) 在APIView的as_view调用父类(django原生)的as_view,还禁用了 csrf 认证
3) 在父类的as_view中dispatch方法请求走的又是APIView的dispatch
1,其中有一句:
view = super().as_view(**initkwargs)
自定义类继承了APIView,在调用时 会走as_view()方法,但是APIView中没有as_view方法,又因为APIView
它继承了View类,在View类中存在as_view()方法,所以此时走的就是View类中存在as_view()方法
2,在View类中存在as_view()方法中
return self.dispatch(request, *args, **kwargs)
此时的self就是Test,所以此时调用的就是父类的dispatch方法,
4) 完成任务方法交给视图类的请求函数处理,得到请求的响应结果,返回给前台
ps:如果继承了 APIView所有的子类,就默认将csrf的中间件给禁用了(即帮你注释了),
因为他自己有认证,他的认证比这高级,而且还可以自定义
在混用的时候,csrf对于原生的django还是使用的,只有继承了APIView的子类,才会拥有drf认证
总结:继承了APIView的视图类,会禁用csrf认证
class APIView(View): # The following policies may be set at either globally, or per-view. # 渲染模块renderer_classes renderer_classes = api_settings.DEFAULT_RENDERER_CLASSES # 解析模块 parser_classes = api_settings.DEFAULT_PARSER_CLASSES # 认证模块 authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES throttle_classes = api_settings.DEFAULT_THROTTLE_CLASSES permission_classes = api_settings.DEFAULT_PERMISSION_CLASSES content_negotiation_class = api_settings.DEFAULT_CONTENT_NEGOTIATION_CLASS metadata_class = api_settings.DEFAULT_METADATA_CLASS versioning_class = api_settings.DEFAULT_VERSIONING_CLASS
def dispatch(self, request, *args, **kwargs): """ `.dispatch()` is pretty much the same as Django's regular dispatch, but with extra hooks for startup, finalize, and exception handling. """ # 在这里是对象获取自己的属性 self.args = args self.kwargs = kwargs request = self.initialize_request(request, *args, **kwargs) self.request = request self.headers = self.default_response_headers # deprecate? try: # 下面这句话执行出异常就会走drf提供的异常 response = self.handle_exception(exc) self.initial(request, *args, **kwargs) # Get the appropriate handler method if request.method.lower() in self.http_method_names: handler = getattr(self, request.method.lower(), self.http_method_not_allowed) else: # 原生django提供的异常 handler = self.http_method_not_allowed response = handler(request, *args, **kwargs) # drf提供的异常 except Exception as exc: #原生的数据 response = self.handle_exception(exc) # 在这里判断是浏览器发来的还是页面发来的(请求方式)再加以包装最终返回数据 self.response = self.finalize_response(request, response, *args, **kwargs) return self.response