drf:APIView请求生命周期,请求模块,解析模块,响应模块,渲染模块

DRF框架---第01天

项目创建

settings.py文件配置

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'corsheaders',  #解决跨域问题
    'app01.apps.App01Config',
    'amp',	注册应用

]
CORS_ORIGIN_ALLOW_ALL=True

LANGUAGE_CODE = 'zh-hans'

TIME_ZONE = 'Asia/Shanghai' #django规定的时区




CORS跨域问题(同源策略)

同源:http协议相同、ip服务器地址相同、app应用端口相同
跨域:协议、ip地址、应用端口有一个不同,就是跨域

Django默认是同源策略,存在跨越问题。
Django的解决方案:

1)Django按照cors模块:
    >: pip install django-cors-headers
    
2)在settings注册模块,配置中间件:
    INSTALLED_APPS = [
        ...
        'corsheaders'
    ]
    MIDDLEWARE = [
        ...
        'corsheaders.middleware.CorsMiddleware'
    ]

3)在settings开启允许跨越:
    CORS_ORIGIN_ALLOW_ALL = True

drf01---urls.py文件

from django.conf.urls import url,include

urlpatterns=[
    url(r'^amp/',include('amp.urls')),
]
下面开始创建amp项目
Python manage.py startapp amp
然后amp文件创建urls.py文件

amp文件中对urls.py,models.py ,views.py文件进行书写

urls.py

from amp import views
from  django.conf.urls import url,include


urlpatterns=[
    drf采用CBV视图
    url(r'^books/$',views.BookAPIView.as_view()),
    url(r'^books/(?P<pk>d+)/$',views.BookAPIView.as_view())
    
]

views.py

一个视图类可以保护常规5个请求方法: get    post   patch      put         delete
5个请求方法处理十个资源操作的逻辑:单群查  单群增  单群整体改   单群局部改    单群删
import rest_framework
from django.http import JsonResponse
from django.views import View
from django.shortcuts import render
from rest_framework.views import APIView	导入视图类
from . import models


class BookView(View):
    def single_get(self,pk):
        book_dic=models.Book.objects.filter(pk=pk).values('name','price').first()
        if not book_dic:
            return	JsonResponse({
                'status':1,
                'msg':'单查,资源不存在'
            })
        return JsonResponse({
            'status':0,
            'msg':'单查OK',
            'results':book_dic
        })
    
    def many_get(self):
        book_query=models.Book.objects.values('name','price')
        book_list=list(book_query)
        return JsonResponse({
            'status':0,
            'msg':'群查OK',
            'results':book_list
        })
    
    get请求方法
    def get(self,request,*args,**kwargs):
        pk=kwargs.get(pk)
        if pk:
            单查
            return self.single_get(pk)
        else:
            群查
            return self.many_get()
        





models.py

from django.db import models

class Book(models.Model):
    name=models.CharField(max_length=32)
    price=models.DecimalField(max_digits=6,decimal_places=2)

访问的接口

接口参数:
url+请求方式+项目访问路径+参数(有参单查,无参群查)
https://127.0.0.1:8000/amp/books		get请求
        群查
https://127.0.0.1:8000/amp/books/2		get请求
        单查

DRF框架---第02天

rest_framework 框架的封装特点:

import rest_framework
from rest_framework.views import APIView

class BookAPIView(APIView):
    def get(self,request,*args,**kwargs):
        return Response({
            'msg':'apiview get ok'
        })
    
    def post(self,request,*args,**kwargs):
        return Response({
            'msg':'apiview post ok'
        })

导入视图类	from rest_framework.views import APIView
导入请求     from rest_framework.request import Request
导入响应	 from rest_framework.response import Response
导入异常	 from rest_framework.exceptions import APIException
导入分页	from rest_framework.pagination import PageNumberPagination
导入配置	from rest_framework.settings import APISettings
导入解析	from rest_framework.parsers import JSONParser
导入排序过滤器		from rest_framework.filters import OrderingFilter

1.APIView的请求生命周期

1.APIView的类继承View类,重写了as_view 和 dispatch 方法
2.重写的as_view方法,主体还是View的as_view,只是在返回视图view函数地址时,局部禁用csrf认证
3.重写的dispatch方法:
		在执行请求逻辑前:请求模块(二次封装request),解析模块(三种数据包格式的数据解析)
    	在执行请求逻辑中:异常模块(执行出现任何异常交给异常模块处理)
        在执行请求逻辑后:响应模块(二次封装response),渲染模块(响应的数据可以通过json或者页面两种方式渲染)

2.请求模块

1.将wsgi的request对象转化成drf的Request类的对象
2.封装后的request对象完全兼容wsgi的request对象,并且将元request保存在新的request._request中
3.重写格式化请求数据存放位置
		拼接参数:request.query_params
    	数据包参数:request.data

源码分析:
入口:APIView的dispatch方法的request=self.initialize_reuqest(request,*args,**kwargs)
print(request._request.method)        在内部将wsgi的request赋值给request._request
print(request.method)	就是通过__getattr__走的是request._request.method
print(request.query_params)	   走的是方法属性,就是给request._request.GET重新命名
print(request.data)		走的是方法属性,值依赖于request._full_data

3.解析模块

只处理数据包参数 -form-data , urlencoded , json
1.全局配置所有视图类的解析方式,解析配置可以配置三种
2.局部配置当前视图类的解析方式,解析配置可以配置三种
3.配置的查找顺序:局部(视图类的类属性)=》全局(settings文件的drf配置)=》默认(drf的默认配置)

解析模块作为了解,但是全局局部配置是重点

源码分析:
入口:APIView的dispatch方法的request=self.initialize_request(request,*agrs,**kwargs)
获取解析类:parsers=self.get_parsers()
进行局部全局配置查找顺序进行查找:return [parser() for parser in self.parser_classes]

4.响应模块

data:响应模块
status:响应的网络状态码
------------------------------------
template_name:drf完成前后台不分离返回页面,但是就不可以返回data--(仅作了解)
headers:响应头,一般不规定,默认
exception:一般异常响应,会佳宁其设置成true,默认false(不设置也没事)
content_type:默认的就是  application/json, 不需要处理
    

5.渲染模块(了解)

Postman请求结果是json格式,浏览器请求结果是页面
可以全局和局部配置

BookAPIView类代码

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.parsers import JSONParser,FormParser,MultiPartParser
from rest_framework.renders import JsonRenderer,BrowsableAPIRenderer
from rest_framework import status

class BookAPIView(APIView):
    局部配置解析类:只适用当前视图类
    parser_classes = [JSONParser,FormParser,MultiPartParser]
    局部配置渲染类:只使用当前视图类
    render_classes = [JSONRenderer,BrowsableAPIRenderer]
    
    def get(self,request,*args,**kwargs):
        response=Response(
            data={
                'msg':'apiview get ok'
            },
            status=status.HTTP_404_NOT_FOUND,
        )
        print(response.data)
        return response
    
    def post(self,request,*args,**kwargs):
        print(request.request.method) 在内部将wsgi的request赋值给request._request
        print(request.method)  就是通过__getattr__走的是request._request.method
        print(request.query_params)  走的是方法属性,就是给request._request.GET重新命名
        print(request.data) 走的是方法属性,值依赖于request._full_data
        
        return Response({
            'msg':'apiview post ok'
        })
    





drf中现在所用到过的模块和导入方法

drf中现在所用到过的模块和导入方法
import rest_framework
from rest_framework.views import APIView
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.exceptions import APIException
from rest_framework.pagination import PageNumberPagination
from rest_framework.settings import APISettings
from rest_framework.parsers import JSONParser
from rest_framework.filters import OrderingFilter
from django.views import View
from rest_framework.views import APIView
from rest_framework.response import Response

from rest_framework.parsers import JSONParser, FormParser, MultiPartParser
from rest_framework.renderers import JSONRenderer, BrowsableAPIRenderer
from rest_framework import status

day02内容总结

1.APIView请求生命周期
APIView的as_viewe(局部禁用csrf)=》走父级的as_view调用dispatch分发请求=》APIView自己重写了dispatch,使用自己完成分发=》分发前完成request二次封装,数据解析=》三大认证=》请求的实际响应(自己的视图类的处理分发)=》出现了异常,就会交给异常模块处理异常=》响应模块完成响应,渲染模块可以json或浏览器两种方式渲染

2.请求模块
request._request 被request完全兼容
request.query_params | request.data

3.解析模块:
局部配置:parser_classes=[JSONParser,FormParser,MultiPartParser]
全局配置:
'DEFAULT_PARSER_CLASSES':[
    'rest_framework.parsers.JSONParser',
    'rest_framework.parsers.FormParser',
    'rest_framework.parsers.MultiPartParser',
]

4.响应模块:
Response(daata=常量|列表|字典,status=网络状态码)

5.渲染模块:
	局部配置:renderer_classes=[JSONRenderer,BrowsableAPIRenderer]
    全局配置:
    'DEFAULT_RENDERER_CLASSES':[
        'rest_framework.renderers.JSONRenderer',
        'rest_framework.renderers.BrowsableAPIRenderer',上线后尽量关闭
    ]
6.异常模块
settings中配置:'EXCEPTION_HANDLER':'api.exception.exception_handler'
    重写exception_handler方法
    
一定要在settings文件中将异常模块配置自己的异常处理函数
from rest_framework.views import exception_handler as drf_exception_handler
from rest_framework.response import Response
先交给drf处理客户端异常,如果结果response为none代表服务器异常,自己处理
最终一定要在日志文件中记录异常现象
def exception_handler(exc,context):
    response=drf_exception_handler(exc,context)
    detail ='%s - %s -%s' % (context.get('view'),context.get('request').method,exc)
    if not response:	服务端错误
        response=Response({'detail':detail})
    else:
        response.data={'detail':detail}
        
        核心:要把response.data.get('detail')信息记录到日志文件
        logger.waring(response.data.get('detail'))
        
        return response
    
原文地址:https://www.cnblogs.com/ludundun/p/12093538.html