REST-Framework: 序列化组件

目录

序言:Django自带序列化组件

一、restframework介绍

什么是restframework

restframework介绍

HTTP动词

状态码

二 rest-framework序列化之Serializer

序列化的意义:

常用字段类型:

序列化实例

三 rest-framework序列化之ModelSerializer

四 生成hypermedialink(极少数)

 五 序列化组件之请求数据校验和保存功能

序列化组件源码分析


序言:Django自带序列化组件

也就是使用原生的django来处理请求

详见

在正式开始介绍Rest-Framework之前我们需要对它有一定的了解:

一、restframework介绍

什么是restframework

django restframework是基于django和restful协议开发的框架,在restful协议里,一切皆是资源,操作是通过请求方式控制,可以将python中的对象转换成json格式的字符串

restframework介绍

在开发REST API的视图中,虽然每个视图具体操作的数据不同,但增、删、改、查的实现流程基本套路化,所以这部分代码也是可以复用简化编写的:

增:校验请求数据 -> 执行反序列化过程 -> 保存数据库 -> 将保存的对象序列化并返回
删:判断要删除的数据是否存在 -> 执行数据库删除
改:判断要修改的数据是否存在 -> 校验请求的数据 -> 执行反序列化过程 -> 保存数据库 -> 将保存的对象序列化并返回
查:查询数据库 -> 将数据序列化并返回
Django REST framework可以帮助我们简化上述两部分的代码编写,大大提高REST API的开发速度。

HTTP动词

对于资源的具体操作类型,由HTTP动词表示。

常用的HTTP动词有下面四个(括号里是对应的SQL命令)。

GET(SELECT):从服务器取出资源(一项或多项)。
POST(CREATE):在服务器新建一个资源。
PUT(UPDATE):在服务器更新资源(客户端提供改变后的完整资源)。
DELETE(DELETE):从服务器删除资源。
还有三个不常用的HTTP动词。

PATCH(UPDATE):在服务器更新(更新)资源(客户端提供改变的属性)。
HEAD:获取资源的元数据。
OPTIONS:获取信息,关于资源的哪些属性是客户端可以改变的。

状态码

200 OK - [GET]:服务器成功返回用户请求的数据,该操作是幂等的(Idempotent)。

201 CREATED - [POST/PUT/PATCH]:用户新建或修改数据成功。

202 Accepted - [*]:表示一个请求已经进入后台排队(异步任务)

204 NO CONTENT - [DELETE]:用户删除数据成功。

400 INVALID REQUEST - [POST/PUT/PATCH]:用户发出的请求有错误,服务器没有进行新建或修改数据的操作,该操作是幂等的。

401 Unauthorized - [*]:表示用户没有权限(令牌、用户名、密码错误)。

403 Forbidden - [*] 表示用户得到授权(与401错误相对),但是访问是被禁止的。

404 NOT FOUND - [*]:用户发出的请求针对的是不存在的记录,服务器没有进行操作,该操作是幂等的。

406 Not Acceptable - [GET]:用户请求的格式不可得(比如用户请求JSON格式,但是只有XML格式)。

410 Gone -[GET]:用户请求的资源被永久删除,且不会再得到的。

422 Unprocesable entity - [POST/PUT/PATCH] 当创建一个对象时,发生一个验证错误。

500 INTERNAL SERVER ERROR - [*]:服务器发生错误,用户将无法判断发出的请求是否成功

 

更多状态码看这里:更多的状态码

下面我们主要介绍使用CBV在视图中处理请求的方式来, 

在这里我们还是简单说一下,为什么使用CBV而不采用FBV:

之前介绍Django的时候我们使用的基本上都是FBV, 虽然函数简单明了,但如果只用函数来开发,有很多面向对象的优点就错失了(继承、封装、多态)。所以Django在后来加入了CBV。可以让我们用类写View,然后通过反射执行as_view()方法,这样做的优点主要下面两种:

提高了代码的复用性,可以使用面向对象的技术,比如Mixin(多继承)
可以用不同的函数针对不同的HTTP方法处理,而不是通过很多if判断,提高代码可读性

下面我就正式开始介绍使用rest-framework在Django中处理请求,

注意:
1.记得使用之前没有安装Djangorestframework模块的要安装好该模块
2.安装成功之后一定要在setting中将rest_framework注册之后才能正常使用

二 rest-framework序列化之Serializer

序列化的意义:

web有两种应用模式,一种是前后端不分离,一种是前后端分离,当前后端分离的时候,后端只需要向前端传输数据即可,不需要进行其他的操作,而restframework在前后端传输数据时,主要是json数据,过程中就要需要把其他数据转换成json数据,比如数据库查询所有数据时,是queryset对象,那就要把这对象处理成json数据返回前端,一般如果是中大型公司,都是前后端分离,这也是目前的市场规则需要.

然后我们来看序列化时常用的字段和通用参数:

常用字段类型:

常用字段类型
字段  字段构造方式和参数默认值
   BooleanField BooleanField()
NullBooleanField NullBooleanField
CharField CharField(max_length=None, min_length=None, allow_blank=False, trim_whitespace=True)
EmailField EmailField(max_length=None, min_length=None, allow_blank=False)
SlugField SlugField(maxlength=50, min_length=None, allow_blank=False) 正则字段,验证正则模式 [a-zA-Z0-9-]+
URLField URLField(max_length=200, min_length=None, allow_blank=False)
IntegerField IntegerField(max_value=None, min_value=None)
FloatField FloatField(max_value=None, min_value=None)
DecimalField DecimalField(max_digits, decimal_places, coerce_to_string=None, max_value=None, min_value=None)
max_digits: 最多位数
decimal_palces: 小数点位置
DateTimeField DateTimeField(format=api_settings.DATETIME_FORMAT, input_formats=None)
DateField DateField(format=api_settings.DATE_FORMAT, input_formats=None)
TimeField TimeField(format=api_settings.TIME_FORMAT, input_formats=None)
DurationField DurationField()
ChoiceField ChoiceField(choices)
choices与Django的用法相同
FileField FileField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL)
ImageField ImageField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL)
ListField ListField(child=, min_length=None, max_length=None)
DictField DictField(child=)

 

相对而言,常用字段类型是比较常见的,在我们的ORM模式里,只要是连接数据库那么就一定需要定义我们的模型参数,下面介绍静态常用的模型参数

通用参数
 

参数名称 说明
max_length 最大长度
min_lenght 最小长度
read_only 表明该字段仅用于序列化输出,默认False
write_only 表明该字段仅用于反序列化输入,默认False
required 表明该字段在反序列化时必须输入,默认True
default 反序列化时使用的默认值
allow_null 表明该字段是否允许传入None,默认False
validators 该字段使用的验证器
error_messages 包含错误编号与错误信息的字典
label 用于HTML展示API页面时,显示的字段名称
help_text 用于HTML展示API页面时,显示的字段帮助提示信息

这里比较常用的字段是前面六个,其中max_length和min_length一般配合着charfield使用,可以给该字段设置大小上下限。而read_only和write_only是两个相反的概念,前者是不接收客户端的数据,只向客户端输出数据,后者是只接收客户端的数据,不向客户端输出数据,这就可以类比于我们登录注册时的密码框,我们只需要向它写入而并不需要它像我们输出,并且该字段是经过hash加密的,寻常情况难以解密

序列化实例

Models部分:
首先在应用的models中建立原始的数据库模型

from django.db import models



# Create your models here.





class Book(models.Model):

title=models.CharField(max_length=32)

price=models.IntegerField()

pub_date=models.DateField()

publish=models.ForeignKey("Publish")

authors=models.ManyToManyField("Author")

def __str__(self):

return self.title



class Publish(models.Model):

name=models.CharField(max_length=32)

email=models.EmailField()

def __str__(self):

return self.name



class Author(models.Model):

name=models.CharField(max_length=32)

age=models.IntegerField()

def __str__(self):

return self.name

 

view部分:

在对数据库中取出来的数据进行序列化的时候的步骤:

  • 需要写一个类来继承serializers.Serializer, 这个类可以单独写一个文件(建议), 也可以直接在view中书写,

  • 书写的这个类中序列化的字段要和数据库中字段要保持高度一致

不一致的时候我们就要介绍一下在序列化的时候使用到的一个参数source:
source可以在后面指定要序列化的字段, 然后再序列化的类中字段就可以自己命名了
 1 变量名和source指定的值不能一样
 2 source='publish.name'还支持继续使用点语法
 3 source 还支持方法(没啥用)
 4 支持写方法对字段进行序列化, 如下
           方法的返回值,会赋给前面定义的序列化的字段名字
           方法一定传一个参数,是当前序列化的表对象
           写方法的时候时固定写法,get_字段名(self, obj):pass
            publish_dic=serializers.SerializerMethodField()
            def get_publish_dic(self,obj):
                    这个obj是当前book对象.
                    return {'id':obj.publish.pk,'name':obj.publish.name}

from rest_framework.views import APIView

from rest_framework.response import Response

from .models import *

from django.shortcuts import HttpResponse

from django.core import serializers





from rest_framework import serializers

# 为序列化做准备

class BookSerializers(serializers.Serializer):

title=serializers.CharField(max_length=32)

price=serializers.IntegerField()

pub_date=serializers.DateField()

# 想要publish字段显示出版社名字的时候

publish=serializers.CharField(source="publish.name")

#authors=serializers.CharField(source="authors.all")

authors=serializers.SerializerMethodField()

def get_authors(self,obj):

temp=[]

for author in obj.authors.all():

temp.append(author.name)

return temp

  #此处可以继续用author的Serializers,

  # def get_authors(self,obj):

    # ret=obj.authors.all()

    # ss=AuthorSerializer(ret,many=True)

    # return ss.data





# 序列化

class BookViewSet(APIView):



def get(self,request,*args,**kwargs):

book_list=Book.objects.all()

# 序列化方式1:

# 单个数据对象 model_to_dict(obj),是Django中的一个方法:返回一个字典,key是obj 这个

# 对象的字段名,value是字段对应的值。这种是最快的一种序列化的方式。

# from django.forms.models import model_to_dict

# import json

# data=[]

# for obj in book_list:

# data.append(model_to_dict(obj))

# print(data)

# return HttpResponse("ok")



# 序列化方式2:

# data=serializers.serialize("json",book_list)

# return HttpResponse(data)



# 序列化方式3:

bs=BookSerializers(book_list,many=True) #many=True代表有多条数据,如果只有一条 数据,many=False

return Response(bs.data)

     # 序列化方式4:

   # ret=models.Book.objects.all().values('nid','title')

     # dd=list(ret)

# return HttpResponse(json.dumps(dd))

 

注意:

1. source 如果是字段,会显示字段,如果是方法,会执行方法,不用加括号(authors=serializers.CharField(source='authors.all'))

2. rest-framework中对request和response都做了处理, 我们来看一下request在rest-framework中的请求流程及相关处理:

rest-framework中的request对象不再是Django中原生的HttpRequest对象, 而是rest-framework提供的扩展了HttpRequest类的Request类的对象

REST framework 提供了Parser解析器,在接收到请求后会自动根据Content-Type指明的请求数据类型(如JSON、表单等)将请求数据进行parse解析,解析为类字典对象保存到Request对象中。

它和django大致相同,因为它的APIView继承是django的View,但在APiView中重写了dispatch方法

看到这段代码:

url(r'^publishers/$', views.PublishViewSet.as_view(),name="publish_list"),

执行PublishViewSet就是APIView的as_view方法

class APIView(View):

APIView继承了View,APIView中有as_view方法,所以会执行这个方法,方法中有这么一句代码

view = super(APIView, cls).as_view(**initkwargs)

最终还是执行了父类里的as_view方法,所以最终执行结果,得到这么这个view函数。
  下面我们就去源码中看看这个函数的执行顺序:

         def view(request, *args, **kwargs):

            self = cls(**initkwargs)

            if hasattr(self, 'get') and not hasattr(self, 'head'):

                self.head = self.get

            self.request = request

            self.args = args

            self.kwargs = kwargs

            return self.dispatch(request, *args, **kwargs)

 

当请求来时,会执行view函数,然后结果调用了dispatch方法,而这里dispatch方法则不是View里的,因为APIView中重写了父类中的dispatch方法,并且是整个rest_framework中最重要的部分,实现了大部分逻辑。  

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:

            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:

                handler = self.http_method_not_allowed



            response = handler(request, *args, **kwargs)



        except Exception as exc:

            response = self.handle_exception(exc)



        self.response = self.finalize_response(request, response, *args, **kwargs)

        return self.response

 


所以我们可以总结,dispatch是通过view的函数的执行而被调用,那么它返回的结果就是view函数返回的结果,而view函数返回的结果就是as_view()方法返回的结果。也就是通过这样的方式获取到了请求方式并执行。

3. 使用rest-framework的Response的时候, 服务器端会根据请求的不同请求客户端而发送给客户端不同的数据, 比如使用浏览器访问的时候,会返回一个完整的带数据和格式的页面, 而使用postman进行访问的时候,只返回一个json格式的数据, 当然这两种方式返回的主要数据-json格式的数据都是一样的,只是一个带页面一个不带页面而已

如在模型中定义一个方法,直接可以在source指定执行

class UserInfo(models.Model):

user_type_choices = (

(1,'普通用户'),

(2,'VIP'),

(3,'SVIP'),

)

user_type = models.IntegerField(choices=user_type_choices)



username = models.CharField(max_length=32,unique=True)

password = models.CharField(max_length=64)





#视图

ret=models.UserInfo.objects.filter(pk=1).first()

aa=ret.get_user_type_display()



#serializer

xx=serializers.CharField(source='get_user_type_display')

 序列化器的字段校验功能

# 三种方式
    -字段自己的校验规则(max_length...)
    -validators的校验
        publish = serializers.CharField(max_length=32,validators=[check,])

        def check(data):
        if len(data)>10:
            raise ValidationError('最长不能超过10')
        else:
            return data
    -局部和全局钩子
        # 局部钩子,validate_字段名,需要带一个data,data就是该字段的数据
    def validate_title(self, data):
        if data.startswith('sb'):
            raise ValidationError('不能以sb开头')
        else:
            return data
    # 全局钩子
    def validate(self, attrs):
        title=attrs.get('title')
        publish=attrs.get('publish')
        if title==publish:
            raise ValidationError('书名不能跟出版社同名')
        else:
            return attrs

read_only 和 write_only

 read_only    表明该字段仅用于序列化输出,默认False
    write_only    表明该字段仅用于反序列化输入,默认False
    
    
    class BookSerializer(serializers.Serializer):
        # 要序列化哪个字段
        id = serializers.IntegerField(required=False)
        # id=serializers.CharField()
        title = serializers.CharField(max_length=32,min_length=2,read_only=True)
        price = serializers.DecimalField(max_digits=5, decimal_places=2)
        # 序列化的时候看不到
        publish = serializers.CharField(max_length=32,validators=[check,],write_only=True)

修改,删除接口

view

   def put(self, request, id):
        # 通过id取到对象
        res = {'code': 100, 'msg': ''}
        try:
            book = models.Book.objects.get(id=id)
            ser = BookSerializer(instance=book, data=request.data)
            ser.is_valid(raise_exception=True)
            ser.save()
            res['msg'] = '修改成功'
            res['result'] = ser.data

        except Exception as e:
            res['code'] = 101
            res['msg'] = str(e)

        return Response(res)
    def delete(self,request,id):
        response = {'code': 100, 'msg': '删除成功'}
        models.Book.objects.filter(id=id).delete()
        return Response(response)
View Code

serializer.py

class BookSerializer(serializers.Serializer):
    id = serializers.IntegerField(required=False)
    title = serializers.CharField(max_length=32,min_length=2)
    price = serializers.DecimalField(max_digits=5, decimal_places=2)
    publish = serializers.CharField(max_length=32)

    def create(self, validated_data):
        res=models.Book.objects.create(**validated_data)
        print(res)
        return res

    def update(self, book, validated_data):
        book.title=validated_data.get('title')
        book.price=validated_data.get('price')
        book.publish=validated_data.get('publish')
        book.save()
        return book
View Code

高级用法之source

1 修改返回到前端的字段名
    # source=title    字段名就不能再叫title
    name = serializers.CharField(max_length=32,min_length=2,source='title')
2 如果表模型中有方法
    # 执行表模型中的test方法,并且把返回值赋值给xxx
    xxx=serializers.CharField(source='test')
3 sourc支持跨表操作
    addr=serializers.CharField(source='publish.addr')
    
# 希望你们去看以下源码,内部如何实现的
View Code

 

三 rest-framework序列化之ModelSerializer

  • 使用modelSerializer的时候一定要指定序列化数据库中的哪张表

  • 使用rest-framework来操作数据库的时候, 对数据进行增、删、改的时候一定要使用modelSerializer序列化过的

  • fields = "__all__":  该表的所有字段都进行序列化

  • fields=['nid', 'name', 'authors'] :  只序列化列表中的字段

  • exclude=('nid') : 除了元组里边的字段之外该表剩下所有字段进行序列化

  • 在modelSerializer同样可以使用SerializerMethodField

  • 在modelSerializer中可以定义局部钩子和全局钩子对某个字段进行二次校验, 或者加逻辑处理

    • 使用钩子的时候也是固定写法, 局部钩子(def validate_字段名(self, value)) | 全局钩子(def validate(self, value))

    • 在这里要注意加局部钩子的时候的代码缩进, 不要将钩子写到Meta中,写进去之后将无法执行钩子

    • 使用局部钩子的时候,注意要传入value参数, 该参数的值是局部钩子要校验的字段的值

class BookSerializers(serializers.ModelSerializer):

class Meta:

model = models.Book

# fields = "__all__"

fields=['nid','title','authors','publish']

# exclude=('nid',) #不能跟fields同时用

# depth = 1 #深度控制,写 几 往里拿几层,层数越多,响应越慢,官方建议0--10之间,个人建议最多3层

publish=serializers.SerializerMethodField()

def get_publish(self,obj):

return obj.publish.name

authors=serializers.SerializerMethodField()

def get_authors(self,obj):

ret=obj.authors.all()

ss=AuthorSerializer(ret,many=True)

return ss.data

 解释:

1 原来用的Serilizer跟表模型没有直接联系, 模型类序列化器ModelSerilizer,跟表模型有对应关系

2 使用
    class BookModelSerializer(serializers.ModelSerializer):
        class Meta:
            model=表模型    # 跟哪个表模型建立关系
            fields=[字段,字段] # 序列化的字段,反序列化的字段
            fields='__all__' # 所有字段都序列化,反序列化
            exclude=[字段,字段] # 排除哪些字段(不能跟fields同时使用)
            read_only_fields=['price','publish']  # 序列化显示的字段
            write_only_fields=['title']           # 反序列化需要传入的字段
            extra_kwargs ={'title':{'max_length':32,'write_only':True}}
            depth=1  # 了解,跨表1查询,最多建议写3
        # 重写某些字段
        publish = serializers.CharField(max_length=32,source='publish.name')
        # 局部钩子,全局钩子,跟原来完全一样
3 新增,修改
    -统统不用重写create和update方法了,在ModelSerializer中重写了create和update
View Code

高级用法之SerializerMethodField

class BookSerializer(serializers.Serializer):
    id = serializers.IntegerField(required=False)
    name = serializers.CharField(max_length=32,min_length=2,source='title')
    price = serializers.DecimalField(max_digits=5, decimal_places=2)
    publish = serializers.SerializerMethodField()
    def get_publish(self,obj):
        dic={'name':obj.publish.name,'addr':obj.publish.addr}
        return dic


class BookModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Book
        fields = '__all__'
    publish = serializers.SerializerMethodField()
    def get_publish(self,obj):
        dic={'name':obj.publish.name,'addr':obj.publish.addr}
        return dic
    
    
    
## 第三中方案,使用序列化类的嵌套
class PublishSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Publish
        # fields = '__all__'
        fields = ['name','addr']


class BookModelSerializer(serializers.ModelSerializer):
    publish = PublishSerializer()

    class Meta:
        model = models.Book
        fields = '__all__'
View Code

 

四 生成hypermedialink(极少数)

class BookSerializers(serializers.ModelSerializer):

class Meta:

model = models.Book

fields = "__all__"

# 生成连接,直接查看出版社详情

publish = serializers.HyperlinkedIdentityField(view_name='ttt', lookup_field='publish_id', lookup_url_kwarg='pkk')

authors=serializers.SerializerMethodField()

def get_authors(self,obj):

ret=obj.authors.all()

ss=AuthorSerializer(ret,many=True)

return ss.data

#--------------



res=BookSerializers(ret,many=True,context={'request': request})

#--------------



class Publish(APIView):

def get(self,request,pkk):

print(pkk)

return HttpResponse('ok')

#----路由---

url(r'^publish/(?P<pkk>\d+)$', views.Publish.as_view(),name='ttt'),

 

 五 序列化组件之请求数据校验和保存功能

class BookSerializer1(serializers.Serializer):

title=serializers.CharField(error_messages={'required': '标题不能为空'})



#这种方式要保存,必须重写create方法

 

 通过源码查看留的校验字段的钩子函数

#is_valid---->self.run_validation-(执行Serializer的run_validation)-->self.to_internal_value(data)---(执行Serializer的run_validation:485行)

# 局部钩子

def validate_title(self, value):

from rest_framework import exceptions

raise exceptions.ValidationError('看你不顺眼')

return value



# 全局钩子

def validate(self, attrs):

from rest_framework import exceptions

if attrs.get('title')== attrs.get('title2'):

return attrs

else:

raise exceptions.ValidationError('不想等啊')

 

序列化组件源码分析

'''

序列化组件,先调用__new__方法,如果many=True,生成ListSerializer对象,如果为False,生成Serializer对象

序列化对象.data方法--调用父类data方法---调用对象自己的to_representation(自定义的序列化类无此方法,去父类找)

Aerializer类里有to_representation方法,for循环执行attribute = field.get_attribute(instance)

再去Field类里去找get_attribute方法,self.source_attrs就是被切分的source,然后执行get_attribute方法,source_attrs

当参数传过去,判断是方法就加括号执行,是属性就把值取出来

'''

 many = True源码分析,局部全局钩子源码解析

1 many=True
    -__init__----->一路找到了BaseSerializer---》__new__决定了生成的对象是谁
    
2 入口是is_valid()---》BaseSerializer--》is_valid---》self._validated_data = self.run_validation(self.initial_data)
    -Serializer这个类的:self.run_validation
def run_validation(self, data=empty):
        value = self.to_internal_value(data)  # 局部字段自己的校验和局部钩子校验
        try:
            self.run_validators(value)
            value = self.validate(value)  # 全局钩子的校验
        except (ValidationError, DjangoValidationError) as exc:
            raise ValidationError(detail=as_serializer_error(exc))
        return value
View Code

 

图书的增删查改resful接口案例:

视图层:

class BookSerializers(serializers.ModelSerializer):

class Meta:

model=models.Book

fields='__all__'





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("")
路由:


url(r'^books/$', views.BookView.as_view()),

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

 drf的请求与响应

# Request
    -data :前端以post请求提交的数据都在它中
    -FILES :前端提交的文件
    -query_params:就是原来的request.GET
    -重写了 __getattr__
        -使用新的request.method其实取得就是原生request.method(通过反射实现)
        
 # Response
    -from rest_framework.response import Response
    -data:响应的字典
    -status:http响应的状态码
        -drf提供给你了所有的状态码,以及它的意思
        from rest_framework.status import HTTP_201_CREATED
    -template_name:模板名字(一般不动),了解
    -headers:响应头,字典
    -content_type:响应的编码方式,了解
    
    
 # 自己封装一个Response对象
      class CommonResponse:
        def __init__(self):
            self.code=100
            self.msg=''
        @property
        def get_dic(self):
            return self.__dict__
# 自己封装一个response,继承drf的Response




# 通过配置,选择默认模板的显示形式(浏览器方式,json方式)
    -配置文件方式(全局)
        -如果没有配置,默认有浏览器和json
            -drf有默认配置文件
            from rest_framework.settings import DEFAULTS
            REST_FRAMEWORK = {
            'DEFAULT_RENDERER_CLASSES': (  # 默认响应渲染类
                'rest_framework.renderers.JSONRenderer',  # json渲染器
                'rest_framework.renderers.BrowsableAPIRenderer',  # 浏览API渲染器
            )
            }
    -在视图类中配置(局部)
        -粒度更小
        -class BookDetail(APIView):
            renderer_classes=[JSONRenderer,]
View Code

 https://www.cnblogs.com/liupengfei1123/p/14956539.html

posted @ 2020-11-13 00:03  Οo白麒麟оΟ  阅读(505)  评论(0)    收藏  举报