DRF之源码分析(二)

Django配置

'''
1.应用是否需要在INSTALLED_APPS中注册取决于是否使用到app的一些特殊操作(如数据库相关),可以不用注册,但是注册后,应用的功能都能使用。
结论:所有应用都注册即可

2.数据库配置:在settings.py中完成即可
import pymysql
pymysql.install_as_MySQLdb()
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': '数据库名',
        'USER': '账号',
        'PASSWORD': '密码',
        'HOST': '如果是127.0.0.1,该配置可以省略',
        "PORT": 3306,  # 如果是3306,该配置可以省略
    }
}

3.路由分发
当项目比较庞大时,如果把所有路由匹配关系都写在总路由里,会比较难以管理和维护。所以我们可以将app相关的路由逻辑进行分发。
urlpatterns = [
	url(r'^api/',include('api.urls'))
]
'''

ORM配置回顾

models.py

from django.db import models
class User(models.Model):
    pass

APIView的请求生命周期

1.APIView类继承了原生Django的View类,并重写了as_view方法
"""
1)as_view方法完成路由配置,返回配置函数是 csrf_exempt(view),也就是禁用了csrf认证规则
结论:所有继承APIView的子类,都不受csrf认证规则的限制

2)将请求处理的任务交给dispath方法完成
"""
2.重写的dispatch方法
'''
1.drf在self.initial_request中重新封装了request对象,并向下兼容了django的request属性。

2.然后在self.initial中对request进行了用户、权限、吞吐量认证。

3.利用反射,执行我们自己的视图类对request请求进行处理。

4.在self.finalize_request中对response对象进行处理(如:渲染)

5.最终返回response对象
'''

请求解析模块

'''
1.二次封装了原生django的wsgi协议的request对象,并做了向下兼容(原来request对象的内容,用封装过的request也可以访问)

2.将所有拼接参数都放在request.query_params中,将所有数据包参数都放在request.data中

3.路由的又名无名分组的数据还是保存在args和kwargs
'''

REST_FRAMEWORK = {
    # 解析类根据请求头中的 Content-Type
    'DEFAULT_PARSER_CLASSES': [
        # Content-Type: application/json
        'rest_framework.parsers.JSONParser',
        
        # Content-Type: application/x-www-form-urlencoded
        'rest_framework.parsers.FormParser',
        
        # Content-Type: multipart/form-data
        'rest_framework.parsers.MultiPartParser'
    ],
}

响应渲染模块

'''
1.当三大认证模块和自己处理请求的视图函数类没有出现异常时--源码中我们可以看到if isinstance(response, Response):

2.响应的数据会交给渲染模块来完成数据的悬案,渲染方式有两种:Json格式数据渲染、Browser格式数据渲染
'''
REST_FRAMEWORK = {
    # 响应渲染类
    'DEFAULT_RENDERER_CLASSES': [
        'rest_framework.renderers.JSONRenderer',
        # 如果直接返回api.html会泄露源码 可对api.html进行修改或直接注释掉
        'rest_framework.renderers.BrowsableAPIRenderer',
    ],
}

序列化组件

单表序列化

models.py

class User(models.Model):
    SEX_CHOICES = ((0,'男'),(1,'女'))
    name = models.CharField(max_length=64)
    age = models.IntegerField()
    height = models.DecimalField(max_digits=5,decimal_places=2,default=0)
    sex = models.IntegerField(choices=SEX_CHOICES,default=0)
    icon = models.ImageField(upload_to='icon',default='icon/default.png')

    def __str__(self):
        return self.name

    class Meta:
        verbose_name_plural = '用户表'
serializers.py
from rest_framework import serializers
from . import models


class UserModelSerializer(serializers.ModelSerializer):
    # 是为哪一个model类定制的序列化类
    class Meta:
        model = models.User
        # 设置参与序列化和反序列化的字段
        '''
        插拔式设计:
            在model的类中提前制作好“插头”
            外部选择性使用“插头”即可
        '''
        fields = ['name','age','height','sex','icon']
views.py
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import settings
from . import models
from . import serializers


class UserAPIView(APIView):
    def get(self, request, *args, **kwargs):
        pk = kwargs.get('pk')
        try:
            if pk:
                obj = models.User.objects.get(pk=pk)
                serializer = serializers.UserModelSerializer(obj, many=False)
                print(serializer.data)
                return Response(serializer.data)
            else:
                objs = models.User.objects.all()
                serializer = serializers.UserModelSerializer(objs, many=True)
                print(serializer.data)
                return Response(serializer.data)
        except:
            return Response({'status': 1, 'msg': '请求数据不存在'})

    def post(self, request, *args, **kwargs):
        print(request.data)
        return Response('post ok')

附:源码分析

原文地址:https://www.cnblogs.com/Ghostant/p/12331718.html