zoukankan      html  css  js  c++  java
  • Django REST framework

    序列化器-Serializer

    什么是rest_framework序列化?

    在写前后端不分离的项目时:

      我们有form组件帮我们去做数据校验

      我们有模板语法,从数据库取出的queryset对象不需要人为去转格式

    当我们写前后端分离项目的时:

      我们需要自己去做数据校验

      我们需要手动去转数据格式,因为跨平台数据传输都用json字符串,不能直接jsonqueryset对象

    序列化器的作用

    1 序列化:把python中的对象转成json格式字符串
            序列化器会把模型对象转换成字典,经过response以后变成json字符串
    2 反序列化:把json格式字符串转成python中的对象
            把客户端发送过来的数据,经过request以后变成字典,序列化器可以把字典转成模型3 注意:drf的序列化组件(序列化器)
        把对象(Book,queryset对象)转成字典
        因为有字典,直接丢到Response中就可以了

    序列化,反序列化
        -对象----》json
        -json---》对象
    序列化器
        -定义一个类,继承Serializer
        -在类内些字段(常用字段,和非常用字段)(字段参数)
        -在视图类中,实例化得到一个序列化类的对象,传入要序列化的数据
        -对象.data---》就是字典
        -source

    序列化器的基本使用

    from rest_framework.serializers import Serializer,ModelSerializer
    from rest_framework import serializers
    Serializer是rest_framework原生的序列化组件 ModelSerializer是rest_framework在原生的序列化组件的基础上封装了一层的序列化组件

    用法:1、在用我们的rest_framework序列化组件的时候,我们的视图层都必须写视图类,不能再写视图函数

    
    

       2、我们需要针对每一张模型表写一个类来继承Serailizer或者ModelSerailizer类,

    
    

     注:当我们在视图类里需要对数据进行序列化或者反序列化的时候,在自己定义的类传入需要序列化的数据实例化,

       调用.data即可拿到序列化或者校验后的数据了

    Django REST framework中的Serializer使用类来定义,须继承自rest_framework.serializers.Serializer

    1 写一个序列化的类,继承Serializer
    class BookSerializer(serializers.Serializer):
        # 在这里写要序列化的字段
        # 序列化字段类(有很多,常用的就几个,等同于models中的字段类)
        # 字段类,有很多字段参数()
        name = serializers.CharField()
        price = serializers.IntegerField()
        # publish = serializers.CharField()
    2 在类中写要序列化的字段(常用字段,和非常用字段)(字段参数)
        name = serializers.CharField()
        price = serializers.IntegerField()
    3 在视图类中使用(实例化得到一个序列化类的对象,传入要序列化的数据)
        class BookView(APIView):
        def get(self, request):
            book_list = models.Book.objects.all()
            # instance=None, 要序列化的数据
            # data=empty  ,要反序列化的数据(目前data先不用)
            # many=True 如果序列化多条,一定要写many=True
            book_ser = BookSerializer(instance=book_list, many=True)
            # book_ser.data就是序列化后的数据
            return Response(book_ser.data)
    4 得到序列化后的数据,返回(对象.data---》就是字典)
        book_ser.data
        
    5 字段参数,source,指定要序列化表中的哪个字段
    
    ##########具体操作步骤见下方详细操作#########

    路由层 urls.py

    from django.urls import path
    from app import views
    
    
    urlpatterns = [
        path('admin/', admin.site.urls),
        # 获取所有的书籍信息
        path('books_new/', views.BookView.as_view()),
        # 对某本书进行操作
        path('books_new/<int:id>/', views.BookViewId.as_view()),
      
    
    ]

    模型层 models.py

    from django.db import models
    
    class Book(models.Model):
        name = models.CharField(max_length=32, verbose_name='书名')
        publish = models.CharField(max_length=32, verbose_name='出版社')
        price = models.IntegerField(verbose_name='价格')

    序列化器层 serializer.py

    from rest_framework import serializers
    from app import models
    
    
    # 新建序列化类,继承Serializer
    class BookSerializer(serializers.Serializer):
        # 类中定义和模型表一一对应的字段,在这里写要序列化的字段
        # 序列化字段类(有很多,常用的就几个,等同于models中的字段类)
        # 字段类,有很多字段参数()
        name = serializers.CharField()
        price = serializers.IntegerField()
        publish = serializers.CharField()

    视图层 views.py

    # 获取所有书籍信息
    class BookView(APIView):
        def get(self, request):
            book_list = models.Book.objects.all()
            book_ser = BookSerializer(instance=book_list, many=True)
            # book_ser.data就是序列化后的数据
            return Response(book_ser.data)
    
    """
      instance=None, 要序列化的数据
      data=empty  ,要反序列化的数据(目前data先不用)
      many=True 如果序列化多条,一定要写many=True
    """
    # 对某一本书进行操作
    class BookViewId(APIView):
        # 对某一个进行操作需要带上id
        def get(self, request, id):
            book = models.Book.objects.all().filter(pk=id).first()
            book_ser = BookSerializer(instance=book)
            return Response(book_ser.data)    

     

    source

    1 指定要序列化的字段(数据表中字段)
      publish = serializers.CharField(source='publish.city') # 拿到出版社所在的城市
    2 用的最多:只有一个字段(也可以跨表)

    SerializerMethodField

    用的最多:跨表查((来定制返回的字段)要么是列表,要么是字典)
    publish=serializers.SerializerMethodField()
    def get_publish(self,obj):
            print(obj)
            # return {'name':'sss','city':'sss'}
            return {'name':obj.publish.name,'city':obj.publish.city,'email': obj.publish.email}

     

    在模型表中写方法

    # models.py 表模型中写的
    class Book(models.Model):
        nid = models.AutoField(primary_key=True)
        name = models.CharField(max_length=32)
        price = models.DecimalField(max_digits=5, decimal_places=2)
        publish_date = models.DateField()
    
        publish = models.ForeignKey(to='Publish',to_field='nid',on_delete=models.CASCADE)
        authors=models.ManyToManyField(to='Author')
        def __str__(self):
            return self.name
    
    
        # def publish_name(self):
        #     return self.publish.name
    
        def publish_name(self):
           return {'name':self.publish.name,'city':self.publish.city}
    ​
        @property
        def author_list(self):  # 列表推导式
           return [{'name':author.name,'age':author.age,'id':author.nid}         for author in self.authors.all()]
    ​
    # serializers.py 序列化类中 class BookSerializer(serializers.Serializer): name = serializers.CharField() price = serializers.IntegerField() ​ publish_name = serializers.DictField() author_list = serializers.ListField()

    注意:serializer不是只能为数据库模型类定义,也可以为非数据库模型类的数据定义。serializer是独立于数据库之外的存在。

     

    序列化类常用字段类型及属性

    字段参数针对性分类

    # 针对charfield
    max_length    最大长度
    min_lenght    最小长度
    allow_blank    是否允许为空
    # 针对interfield
    max_value    最小值
    min_value    最大值
    
    # 通用的,大家都有
    # 这两个最重要
    read_only    表明该字段仅用于序列化输出,默认False(序列化)
    write_only    表明该字段仅用于反序列化输入,默认False(反序列化)
    
    
    required    表明该字段在反序列化时必须输入,默认True
    default    反序列化时使用的默认值
    allow_null    表明该字段是否允许传入None,默认False
    error_messages    包含错误编号与错误信息的字典
    
    validators    该字段使用的验证器(了解)

    反序列化,局部钩子,全局钩子

    使用序列化器进行反序列化时,需要对数据进行验证后,才能获取验证成功的数据或保存成模型类对象。

    在获取反序列化的数据前,必须调用is_valid()方法进行验证,验证成功返回True,否则返回False。

    验证失败,可以通过序列化器对象的errors属性获取错误信息,返回字典,包含了字段和字段的错误。如果是非字段错误,可以通过修改REST framework配置中的NON_FIELD_ERRORS_KEY来控制错误字典中的键名。

    验证成功,可以通过序列化器对象的validated_data属性获取数据。

    在定义序列化器时,指明每个字段的序列化类型和选项参数,本身就是一种验证行为。

    1 如果要反序列化,继承了Serializer,必须重写create方法
    
    2 使用
    # 视图类
    def post(self, request):
        publish_ser = serializer.PublishSerializer(data=request.data)
        if publish_ser.is_valid(): # 校验数据
            # 直接保存,保存到哪个表里?需要重写save
            publish_ser.save()
            return Response(publish_ser.data)
        else:
            print(publish_ser.errors)
            return Response('数据有问题啊')
        
    # 序列化类
    def create(self, validated_data):
        # 校验过后的数据
        res = models.Publish.objects.create(**validated_data)
        return res
    """
    父类的save内部调用了create,所以我们重写create
    return res 给了self.instance以后,instance就有值了
    publish_ser.data,instance就有值调用data就能拿到序列化后的数据
    
    is_valid()方法还可以在验证失败时抛出异常serializers.ValidationError,可以通过传递raise_exception=True参数开启,
    REST framework接收到此异常,会向前端返回HTTP 400 Bad Request响应。
    """

    局部和全局钩子

    # validate_字段名    
        def validate_name(self, data):
            # data就是当前字段的值
            if data.startswith('sb'):
                raise ValidationError('不能以sb开头')
            else:
                return data
            
    # 在序列化器中需要同时对多个字段进行比较验证时,可以定义validate方法来验证
        def validate(self, attrs):
            if attrs.get('name') == attrs.get('city'):
                raise ValidationError('city和名字不能一样')
            else:
                return attrs

    模型类序列化器

    如果我们想要使用序列化器对应的是Django的模型类,DRF为我们提供了ModelSerializer模型类序列化器来帮助我们快速创建一个Serializer类。

    ModelSerializer与常规的Serializer相同,但提供了:

    • 基于模型类自动生成一系列字段

    • 基于模型类自动为Serializer生成validators,比如unique_together

    • 包含默认的create()和update()的实现

    视图类 views.py

    class BookView(APIView):
        def get(self,request):
            qs=models.Book.objects.all()
            ser=serializer.BookModelSerializer(instance=qs,many=True)
            return Response(ser.data)
    
        def post(self,request):
            ser = serializer.BookModelSerializer(data=request.data)
            if ser.is_valid():
                ser.save()
                return Response(ser.data)
            else:
                return Response(ser.errors)
    
    
    class BookDetailView(APIView):
        def get(self,request,id):
            book = models.Book.objects.filter(pk=id).first()
            ser = serializer.BookModelSerializer(instance=book)
            return Response(ser.data)
        def put(self,request,id):
            book = models.Book.objects.filter(pk=id).first()
            ser = serializer.BookModelSerializer(instance=book,data=request.data)
            if ser.is_valid():
                ser.save()
                return Response(ser.data)
            else:
                return Response(ser.errors)
    
        def delete(self,request,id):
            res = models.Book.objects.filter(pk=id).delete()
            if res[0] > 0:
                return Response('')
            else:
                return Response('要删的不存在')

    序列化类 serializers.py

    """
    ModelSerializer
    使用步骤:
    1、新建序列化类,继承ModelSerializer
    2、类中定义和模型表一一对应的字段,这里可以定义class Meta() 然后指定模型表model和 映射字段fields,比Serializer更简洁
        -其中类中的名字可以改变,需要在serializers.CharField()的括号中指定source=某个字段,建议映射关系
        -外键关系的字段可以用serializers.SerializerMethodField(),需要在下方固定写 get_字段名 的方法,
            这里可以写具体逻辑,最终返回结果就是该字段的结果
    3、当新增数据的时候不需要重写父类的create方法,这里ModelSerializer做了封装
    4、当修改数据的时候不需要重写父类的update方法,这里ModelSerializer做了封装
    5、当完成这些配置后就可以在视图类中实例化调用了,序列化的时候序列化,反序列化的时候校验
    
    """
    
    from rest_framework import serializers
    from app import models
    
    class BookModelSerializer(serializers.ModelSerializer):
        class Meta:
            model = models.Book  # model 指明参照哪个模型类
            fields = '__all__'  # fields 指明为模型类的哪些字段生成,__all__表名包含所有字段
            
            # 给字段类加属性
            extra_kwargs = {
                'publish': {'required': True, 'write_only': True},
                'authors': {'required': True, 'write_only': True},
            }
        publish_detail = PublishSerializer(source='publish',read_only=True)
        author_list=serializers.ListField(read_only=True)
        # 字段自己的校验,全局钩子,局部钩子
        
    """
    使用fields来明确字段,__all__表名包含所有字段,也可以写明具体哪些字段,如
    使用exclude可以明确排除掉哪些字段
    使用extra_kwargs参数为ModelSerializer添加或修改原有的选项参数
    """

    表模型 models.py

     这是完整的模型表,上面的视图和序列化类只展示了部分表的增删改查演示

    from django.db import models
    
    
    class Book(models.Model):
        nid = models.AutoField(primary_key=True)
        name = models.CharField(max_length=32, verbose_name='书名')
        price = models.DecimalField(max_digits=5, decimal_places=2, verbose_name='价格')
        publish_date = models.DateField(verbose_name='出版时间')
    
        publish = models.ForeignKey(to='Publish',to_field='nid',on_delete=models.CASCADE)
        authors=models.ManyToManyField(to='Author')
        class Meta:
            verbose_name_plural = '书籍表'
    
        def __str__(self):
            return self.name
    
        # 表模型写方法,展示更多字段
        # def publish_name(self):
        #     return self.publish.name
    
        # def publish_name(self):
        #     return {'name':self.publish.name,'city':self.publish.city}
        #
        # @property
        # def author_list(self):
        #     return [{'name':author.name,'age':author.age,'id':author.nid} for author in self.authors.all()]
    
    
    
    class Author(models.Model):
        nid = models.AutoField(primary_key=True)
        name = models.CharField(max_length=32, verbose_name='名字')
        age = models.IntegerField(verbose_name='年龄')
        author_detail = models.OneToOneField(to='AuthorDetail',to_field='nid',unique=True,on_delete=models.CASCADE)class Meta:
            verbose_name_plural = '作者表'
    
        def __str__(self):
            return self.name
    
    
    class AuthorDetail(models.Model):
        nid = models.AutoField(primary_key=True)
        telephone = models.BigIntegerField(verbose_name='电话')
        birthday = models.DateField(verbose_name='生日')
        addr = models.CharField(max_length=64, verbose_name='地址')
        class Meta:
            verbose_name_plural = '作者详情表'
    
    class Publish(models.Model):
        nid = models.AutoField(primary_key=True)
        name = models.CharField(max_length=32, verbose_name='社名')
        city = models.CharField(max_length=32, verbose_name='地址')
        email = models.EmailField(verbose_name='邮箱')
        class Meta:
            verbose_name_plural = '出版社表'
    
        def __str__(self):
            return self.name

    路由urls.py

    urlpatterns = [
      path('books/',views.BookView.as_view()),
      path('books/<int:id>/',views.BookDetailView.as_view()),
    ]

    序列化高级用法

    ModelSerializer用的基本就是下面这个方法
    class BookModelSerializer(serializers.ModelSerializer):
        class Meta:
            model = models.Book
            fields = "__all__"
            
    """
    如果想让字段更丰富些,可以采用任意一种方法实现(方法有很多种)
    第一种方法:source
        publish = serializers.CharField(source='publish.city')
        
    第二种方法:SerializerMethodField
    publish=serializers.SerializerMethodField()
    def get_publish(self,obj):
          return {'name':obj.publish.name,'city':obj.publish.city,'email': obj.publish.email}
          
    第三种方法:在表模型写方法
     def publish_name(self):
            return {'name':self.publish.name,'city':self.publish.city}
    
        @property
        def author_list(self):
            return [{'name':author.name,'age':author.age,'id':author.nid} for author in self.authors.all()]
                   
    
    第四种方法:子序列化
    publish = Publishserializer()
    """

    如果上方的说明还不清晰,可粘贴到项目中运行。django版本2.2.2

    仅演示方法,功能未完善不要在意

    from rest_framework.serializers import ModelSerializer
    from rest_framework import serializers
    from app01 import models
    from rest_framework.exceptions import ValidationError
    
    
    class BookModelSerializer(ModelSerializer):
        class Meta():
            model = models.Book
            fields = "__all__"
        # 需要跟表模型中写的方法对应
        publish_name = serializers.DictField()
        author_list = serializers.ListField()
    
    
    
    class AuthorDatailModelserializer(ModelSerializer):
        class Meta():
            model = models.AuthorDetail
            fields = "__all__"
    
    
    class AuthorModelSerializer(ModelSerializer):
        class Meta():
            model = models.Author
            fields = "__all__"
    
        # 第一种方法:source,只能选择一个字段
        # author_detail = serializers.CharField(source='author_detail.birthday')
    
        # 第二种方法:SerializerMethodField,可多选
        # author_detail = serializers.SerializerMethodField()
        # def get_author_detail(self, obj):
        #     return {'p': obj.author_detail.telephone, 'b': obj.author_detail.birthday}
    
        # 第三种方法:在表模型中写方法,需跟模型表models对应
        # author_detail = serializers.DictField(source='author_detail_name')
    
        # 第四种方法:子序列化(Publishserializer需要在当前类上方提前定义好)
        # author_detail = AuthorDatailModelserializer()
    
    
        # def validate_name(self, data):
        #     if data.startswith('sb'):
        #         raise ValidationError('作者名不能有敏感词汇')
    
    
    class PublishModelSerializer(ModelSerializer):
        class Meta():
            model = models.Publish
            fields = "__all__"
    
        # def validate_name(self, data):
        #     if data.startswith('sb'):
        #         raise ValidationError('出版社名不能有敏感词汇')
    序列化类 serializer.py
    from django.db import models
    
    class Book(models.Model):
        nid = models.AutoField(primary_key=True)
        name = models.CharField(max_length=32, verbose_name='书名')
        price = models.DecimalField(max_digits=5, decimal_places=2, verbose_name='价格')
        publish_date = models.DateField(verbose_name='出版时间')
    
        publish = models.ForeignKey(to='Publish',to_field='nid',on_delete=models.CASCADE)
        authors=models.ManyToManyField(to='Author')
        class Meta:
            verbose_name_plural = '书籍表'
    
        def __str__(self):
            return self.name
    
        # 表模型写方法,展示更多字段
    
        def publish_name(self):
            return {'name':self.publish.name,'city':self.publish.city}
    
        @property
        def author_list(self):
            return [{'name':author.name,'age':author.age,'id':author.nid} for author in self.authors.all()]
    
    
    
    class Author(models.Model):
        nid = models.AutoField(primary_key=True)
        name = models.CharField(max_length=32, verbose_name='名字')
        age = models.IntegerField(verbose_name='年龄')
        author_detail = models.OneToOneField(to='AuthorDetail',to_field='nid',unique=True,on_delete=models.CASCADE)
    
        # 表模型写方法,展示更多字段
        def author_detail_name(self):
            return {'telephone':self.author_detail.telephone, 'birthday':self.author_detail.birthday, 'addr':self.author_detail.addr}
    
        class Meta:
            verbose_name_plural = '作者表'
    
        def __str__(self):
            return self.name
    
    
    class AuthorDetail(models.Model):
        nid = models.AutoField(primary_key=True)
        telephone = models.BigIntegerField(verbose_name='电话')
        birthday = models.DateField(verbose_name='生日')
        addr = models.CharField(max_length=64, verbose_name='地址')
        class Meta:
            verbose_name_plural = '作者详情表'
    
    class Publish(models.Model):
        nid = models.AutoField(primary_key=True)
        name = models.CharField(max_length=32, verbose_name='社名')
        city = models.CharField(max_length=32, verbose_name='地址')
        email = models.EmailField(verbose_name='邮箱')
        class Meta:
            verbose_name_plural = '出版社表'
    
        def __str__(self):
            return self.name
    模型层 models.py
    from django.contrib import admin
    from django.urls import path
    from app01 import views
    
    urlpatterns = [
        path('admin/', admin.site.urls),
        # 查询所有书籍,增加书籍
        path('book/', views.BookView.as_view()),
        # 查询,修改,删除单本书籍
        path('book/<int:pk>/', views.BookDetailView.as_view()),
        # 查询所有作者,增加作者
        path('author/', views.AuthorView.as_view()),
        # 查询,修改,删除单个作者
        path('author/<int:pk>/', views.AuthorDetailView.as_view()),
    ]
    路由层 urls.py
    from django.shortcuts import render
    from rest_framework.views import APIView
    from rest_framework.response import Response
    from rest_framework.request import Request
    from app01 import serializer
    from app01 import models
    
    # 查询所有书籍,增加书籍
    class BookView(APIView):
        def get(self, request):
            books = models.Book.objects.all()
            ser = serializer.BookModelSerializer(instance=books, many=True)
            return Response(ser.data)
    
        def post(self, request):
            ser = serializer.BookModelSerializer(data=request.data)
            if ser.is_valid():
                # 直接保存,保存到哪个表里?需要重写save
                ser.save()
                return Response(ser.data)
    
            return Response(ser.errors)
    
    # 查询,修改,删除单本书籍
    class BookDetailView(APIView):
        def get(self, request, *args, **kwargs):
            book = models.Book.objects.filter(pk=kwargs.get('pk')).first()
            ser = serializer.BookModelSerializer(instance=book)
            print(ser.instance)
            return Response(ser.data)
    
        def put(self, request, *args, **kwargs):
            book = models.Book.objects.filter(pk=kwargs.get('pk')).first()
            ser = serializer.BookModelSerializer(instance=book, data=request.data)
            if ser.is_valid():
                ser.save()
                return Response(ser.data)
            else:
                return Response('数据校验有误')
    
        def delete(self, request, *args, **kwargs):
            book = models.Book.objects.filter(pk=kwargs.get('pk')).delete()
            print(book)
            if book[0] > 0:
                return Response('')
            else:
                return Response('要删的不存在')
    
    # 查看所有作者,增加作者
    class AuthorView(APIView):
        def get(self,request):
            author = models.Author.objects.all()
            ser = serializer.AuthorModelSerializer(instance=author,many=True)
            return Response(ser.data)
    
        def post(self,request):
            ser = serializer.AuthorModelSerializer(data=request.data)
            if ser.is_valid():
                ser.save()
                return Response(ser.data)
            return Response(ser.errors)
    
    # 查看单个作者。。。修改删除功能未完善
    class AuthorDetailView(APIView):
        def get(self,request, *args, **kwargs):
            author = models.Author.objects.filter(pk=kwargs.get('pk')).first()
            ser = serializer.AuthorModelSerializer(instance=author)
            return Response(ser.data)
    视图层 views.py

    序列化类源码分析(了解)

     many参数

    1 序列化类实例化的时候,传了many,序列化多条,不传,就序列化单条
    # many=True,实例化得到的对象是ListSerializer
    ser=serializer.BookModelSerializer(instance=qs,many=True)
    print(type(ser))
    # rest_framework.serializers.ListSerializer
    # 列表中套了很多BookModelSerializer
    
    # many=False,实例化得到的对象是BookModelSerializer
    ser=serializer.BookModelSerializer(instance=book)
    print(type(ser))
    # app01.serializer.BookModelSerializer
    
    
    
    类实例化:在执行__init__之前,先执行了__new__生成一个空对象(决定了是哪个类的对象)
    在__new__中进行判断,如果many=True,就返回ListSerializer的对象

    局部全局钩子的源码分析

    入口 is_valid()
    判断_validated_data如果没有
    执行了 self.run_validation(self.initial_data)
    目前在BaseSerializer,如果按住ctrl点击,会直接进到它父类的run_validation,进到Field,不是真正执行的方法
    
    我们需要从头找,实际上是Serializer类的run_validation
    def run_validation(self, data=empty):
        value = self.to_internal_value(data)#字段自己的校验和局部钩子
        try:
            self.run_validators(value) 
            value = self.validate(value) # 全局钩子
            assert value is not None, 
            except (ValidationError, DjangoValidationError) as exc:
                raise ValidationError(detail=as_serializer_error(exc))
    
                return value
    局部钩子是在  to_internal_value执行的
    def to_internal_value(self, data):
        for field in fields:
            validate_method = getattr(self, 'validate_' + field.field_name, None)
            if validate_method is not None:
                validated_value = validate_method(validated_value)
                
                

    序列化对象.data

    序列化对象.data方法--调用父类data方法---调用对象自己的
    to_representation(自定义的序列化类无此方法,去父类找)
    Serializer类里有to_representation方法
        for循环执行attribute = field.get_attribute(instance)
    再去Field类里去找get_attribute方法,self.source_attrs就是被切分的source
    然后执行get_attribute方法,source_attrs
    
    当参数传过去,判断是方法就加括号执行,是属性就把值取出来

    请求与响应

    请求对象 Request

    REST framework 传入视图的request对象不再是Django默认的HttpRequest对象,而是REST framework提供的扩展了HttpRequest类的Request类的对象。

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

    Request对象的数据是自动根据前端发送数据的格式进行解析之后的结果。

    无论前端发送的哪种格式的数据,我们都可以以统一的方式读取数据。

    常用属性

    1).data
    request.data 返回解析之后的请求体数据。类似于Django中标准的request.POST和 request.FILES属性,但提供如下特性:
    
    包含了解析之后的文件和非文件数据
    包含了对POST、PUT、PATCH请求方式解析后的数据
    利用了REST framework的parsers解析器,不仅支持表单类型数据,也支持JSON数据
    2).query_params
    request.query_params与Django标准的request.GET相同,只是更换了更正确的名称而已

    响应对象 Response

    REST framework提供了一个响应类Response,使用该类构造响应对象时,响应的具体数据内容会被转换(render渲染)成符合前端需求的类型。

    REST framework提供了Renderer 渲染器,用来根据请求头中的Accept(接收数据类型声明)来自动转换响应数据到对应格式。如果前端请求中未进行Accept声明,则会采用默认方式处理响应数据,我们可以通过配置来修改默认响应格式。

    可以在rest_framework.settings查找所有的drf默认配置项

    REST_FRAMEWORK = {
        'DEFAULT_RENDERER_CLASSES': (  # 默认响应渲染类
            'rest_framework.renderers.JSONRenderer',  # json渲染器
            'rest_framework.renderers.BrowsableAPIRenderer',  # 浏览API渲染器
        )
    }

    data数据不要是render处理之后的数据,只需传递python的内建类型数据即可,REST framework会使用renderer渲染器处理data

    data不能是复杂结构的数据,如Django的模型类对象,对于这样的数据我们可以使用Serializer序列化器序列化处理后(转为了Python字典类型)再传递给data参数。

    参数说明:

    #一直会用
    data: 为响应准备的序列化处理后的数据(字典)
    #偶尔会用
    headers: 用于存放响应头信息的字典;
    status: 状态码,默认200;(http请求的状态码)
        
    # 基本不用  
    template_name: 模板名称,如果使用HTMLRenderer 时需指明;
    content_type: 响应数据的Content-Type,通常此参数无需传递,REST framework会根据前端所需类型数据来设置该参数。

    常用属性

    1).data
    传给response对象的序列化后,但尚未render处理的数据
    
    2).status_code
    状态码的数字
    
    3).content
    经过render处理后的响应数据

    所有http状态码

    为了方便设置状态码,REST framewrok在rest_framework.status模块中提供了常用状态码常量。

    1)信息告知 - 1xx
        HTTP_100_CONTINUE = 100
        HTTP_101_SWITCHING_PROTOCOLS = 101
        
    2)成功 - 2xx
        HTTP_200_OK = 200
        HTTP_201_CREATED = 201
        HTTP_202_ACCEPTED = 202
        HTTP_203_NON_AUTHORITATIVE_INFORMATION = 203
        HTTP_204_NO_CONTENT = 204
        HTTP_205_RESET_CONTENT = 205
        HTTP_206_PARTIAL_CONTENT = 206
        HTTP_207_MULTI_STATUS = 207
        HTTP_208_ALREADY_REPORTED = 208
        HTTP_226_IM_USED = 226
        
    3)重定向 - 3xx    
        HTTP_300_MULTIPLE_CHOICES = 300
        HTTP_301_MOVED_PERMANENTLY = 301
        HTTP_302_FOUND = 302
        HTTP_303_SEE_OTHER = 303
        HTTP_304_NOT_MODIFIED = 304
        HTTP_305_USE_PROXY = 305
        HTTP_306_RESERVED = 306
        HTTP_307_TEMPORARY_REDIRECT = 307
        HTTP_308_PERMANENT_REDIRECT = 308
        
    4)客户端错误 - 4xx
        HTTP_400_BAD_REQUEST = 400
        HTTP_401_UNAUTHORIZED = 401
        HTTP_402_PAYMENT_REQUIRED = 402
        HTTP_403_FORBIDDEN = 403
        HTTP_404_NOT_FOUND = 404
        HTTP_405_METHOD_NOT_ALLOWED = 405
        HTTP_406_NOT_ACCEPTABLE = 406
        HTTP_407_PROXY_AUTHENTICATION_REQUIRED = 407
        HTTP_408_REQUEST_TIMEOUT = 408
        HTTP_409_CONFLICT = 409
        HTTP_410_GONE = 410
        HTTP_411_LENGTH_REQUIRED = 411
        HTTP_412_PRECONDITION_FAILED = 412
        HTTP_413_REQUEST_ENTITY_TOO_LARGE = 413
        HTTP_414_REQUEST_URI_TOO_LONG = 414
        HTTP_415_UNSUPPORTED_MEDIA_TYPE = 415
        HTTP_416_REQUESTED_RANGE_NOT_SATISFIABLE = 416
        HTTP_417_EXPECTATION_FAILED = 417
        HTTP_418_IM_A_TEAPOT = 418
        HTTP_422_UNPROCESSABLE_ENTITY = 422
        HTTP_423_LOCKED = 423
        HTTP_424_FAILED_DEPENDENCY = 424
        HTTP_426_UPGRADE_REQUIRED = 426
        HTTP_428_PRECONDITION_REQUIRED = 428
        HTTP_429_TOO_MANY_REQUESTS = 429
        HTTP_431_REQUEST_HEADER_FIELDS_TOO_LARGE = 431
        HTTP_451_UNAVAILABLE_FOR_LEGAL_REASONS = 451
        
    5)服务器错误 - 5xx    
        HTTP_500_INTERNAL_SERVER_ERROR = 500
        HTTP_501_NOT_IMPLEMENTED = 501
        HTTP_502_BAD_GATEWAY = 502
        HTTP_503_SERVICE_UNAVAILABLE = 503
        HTTP_504_GATEWAY_TIMEOUT = 504
        HTTP_505_HTTP_VERSION_NOT_SUPPORTED = 505
        HTTP_506_VARIANT_ALSO_NEGOTIATES = 506
        HTTP_507_INSUFFICIENT_STORAGE = 507
        HTTP_508_LOOP_DETECTED = 508
        HTTP_509_BANDWIDTH_LIMIT_EXCEEDED = 509
        HTTP_510_NOT_EXTENDED = 510
        HTTP_511_NETWORK_AUTHENTICATION_REQUIRED = 511
    
    
        #drf推荐的写法
        return Response(ser.data,status.HTTP_200_OK)

    drf 整体内容概述

    0 drf是django的一个app
        -序列化器
        -Request
        -Response
        -版本控制
        -认证,频率,权限
        -过滤,排序,分页
        -视图相关
        -自动生成接口文档(coreapi,swagger)
        -jwt做认证(第三方)
        -xadmin---》对admin的美化(bootstrap+jq,1.x版本),simple-ui
        -RBAC:基于角色的访问控制(公司内部项目)
        
        
    1 序列化器
        1. 序列化,序列化器会把模型对象转换成字典,经过response以后变成json字符串
        2. 反序列化,把客户端发送过来的数据,经过request以后变成字典,序列化器可以把字典转成模型
        3. 反序列化,完成数据校验功能
        
    2 Serializer
        -序列化
            -实例化序列化对象,many参数作用
            -source
            -SerializerMethodField
            -模型表中写方法    
        -反序列化
            -ser=BookSerializer(data=request.data)
            -数据校验:ser.is_valid()
            -存数据:手动存,重写BookSerializer的create方法,update方法
            -ser.save() 如果是新增,会调用create,如果是修改,会调用update
            -ser.data 如果有instance对象,就是对instance做序列化
            -全局,局部钩子,字段参数
    3 ModelSerializer -class Meta: model=Book fields=‘__all__’ extra_kwargs -重写某个字段:跟之前学的又一样了 -子序列化
    4 常用非常用字段
    5 字段参数
    6 如果第三张表是手动建的,authors是存不进去的 { name:ddd price:10 publish:1 authors:[1,2] } 7 请求对象的属性 8 响应对象 -data:响应数据 -status:响应状态码 -header:响应头 -content_type:响应类型 9 加入serializer后整个后端逻辑
    从来就没有正确的选择,我们只不过是要努力奋斗,使当初的选择变得正确。
  • 相关阅读:
    java控制台程序打包为jar
    idea 配置自定义模板
    git clone 使用用户名和密码
    (办公)轻松学redux
    (办公)轻松学 React-Router 4(20210401)
    (办公)探秘react教程20210331
    (办公)html5与css3的相关知识
    删除临时表空间
    windows如何拉取一个文件夹下的所有文件名
    数据文件resize回收空间
  • 原文地址:https://www.cnblogs.com/gfeng/p/14658470.html
Copyright © 2011-2022 走看看