$序列化组件$

【一】补充知识

【1】http中get请求能不能再请求体中携带数据

  • 可以,但是一般都是post和put请求

【2】get请求与post请求的区别

  1. 首先post请求比get请求更安全

  2. POST请求:可以发送多种类型的数据,包括文本、图片、音频、视频等

  3. GET请求:只能发送ASCII字符,不支持发送二进制数据或大量文本数据

# GET请求:通常用于请求从服务器获取数据,是一个幂等的请求。幂等性意味着对资源的同一GET请求多次执行,返回的结果应该相同且不会对资源产生副作用(如修改服务器上的数据)。GET请求常用于查询操作,例如搜索、排序和筛选等。
​
# POST请求:用于向服务器提交数据以创建新资源或更新现有资源,不是一个幂等的请求。POST请求可能会导致服务器上的状态改变,如创建新资源或更新现有资源。它常用于表单提交、文件上传和在服务器上执行某些操作

【3】小总结

  • django视图类于视图类的request

    • request.POST只针对于post请求的urlencoded编码格式 才有数据

    • request.GET:请求地址栏中参数,无论什么方式,地址栏中都在这里

      • 但是它是这种方式:<QueryDict: {'key': ['key', '99']}>

      • 取出方式

        • 取出一个:request.GET.get("key")

        • 取出所有:request.GET.getlist("key")

    • request.body:无论什么请求,无论什么编码格式,都在里面

  • http的不同编码格式

    • urlencoded:在请求体中是 key=value&key=value

    • json:在请求体中是 {"name":"lqz","age":19}

    • form-data: asdfasdf-------数据部分 asdfasdfasdf-----文件部分

【二】新的Request对象和Response

【1】Request

  • 以后我们写视图,全部用cbv,cbv继承drf的APIView基类--》其实APIView继承了django的View

  • 继承APIView后,响应统一用drf的响应

    • request请求对象:http请求的所有内容,都会在这个对象中

    • 继承APIView后的request对象和django的request的对象完全是两个不同的对象

      • drf的request:rest_framework.request.Request

      • django的request:django.core.handlers.wsgi.WSGIRequest

    • 但是drf的request用起来的和原来的request是一样的

      • print(request.method)
        print(request.POST)
        print(request.GET)
        print(request.get_full_path())

    • request.data:

      • 无论那种编码格式,请求体的数据,都在里面

        • urlencoded,form-data:是QueryDict的对象

        • json:是普通字典对象

        • 单是都当字典用即可

      • 但是由于编码格式的不同,可能是不同类的对象

    • reques.FILES:

      • 前端传文件还是从这里面取

    • request.query_params:

      • 查询?后面的参数

【2】Response

  • 导入

from rest_framework.response import Response
  • 使用

    • 直接放字典,列表,字符串

      • 是被放在了响应体中

  • 放状态码

    • Response("ok",status=201)

  • 如何放响应头:

    • Response("ok",status=201,headers={"xx":"xx})

  • 总结:Response

    • data:响应体可以传字典,列表,字符串

    • status:http的响应状态码---》drf封装了所有常量--》HTTP_200_OK = 200

    • template_name :忽略----指定使用浏览器访问回来的模板,没有写的话,默认模板

    • headers:响应头

    • exception:异常

    • content_type:响应的编码格式,一般不用,大部分都用json

【三】序列化类的介绍

  • 序列化类的作用:

    • 前端传json格式的字符串给后端--》后端需要保存到数据库--》这个过程称之为反系列化

    • 后端从数据库查出来的对象--》以json格式字符串传给前端--》这个过程称之为序列化

  • serializer就是为了完成上面的操作

    • 完成序列化

    • 反序列化

    • 还有一个:反序列化校验

【四】序列化类的快速使用

【1】使用序列化类的使用步骤

  1. 首先创建一个序列化文件夹serializer.py

  2. 在里面创建创建一个序列化类,这个序列化类继承Serializer

    from rest_framework import serializers
    ​
    ​
    # 定义序列化类,定义的序列化类要与,models里面定义的字段类都对应
    class StudentSerializer(serializers.Serializer):
        # 定义的序列化字段的类型也要一样,里面不用写限制条件
        name = serializers.CharField()
        age = serializers.IntegerField()
        gender = serializers.IntegerField()
    • moderls.py

    • from django.db import models
      ​
      ​
      # 创建学生的模型表
      class Student(models.Model):
          name = models.CharField(max_length=32)
          age = models.IntegerField()
          gender = models.IntegerField(choices=((1, '男'), (2, '女'), (3, '未知')))

  3. 在类中要写序列化的字段,这个序列化类里面的字段要与models里面的字段和字段类型一一对应

  4. 在视图类中使用

# 使用DRF种的Request返回序列化的数据
from rest_framework.response import Response
# 让视图类继承的父类
from rest_framework.views import APIView
# 导入模型表
from .models import Student
# 导入序列化类
from .serializer import StudentSerializer
​
​
# 在视图类中查询所有数据信息,用视图类继承APIView父类
class StudentView(APIView):
    # 查询所有数据
    def get(self, request):
        data_all = Student.objects.all()
        # print(data_all)
        # 用你定义的序列化类,进行序列化
        # instance:对应的是数序列化的数据
        # many: 当它为True是代表序列化的实例不止一条
        # 反之:当为False是序列化的实例只能是一条
        # serializer对象:将包含序列化后的数据,但此时数据还没有被渲染成最终的响应体
        serializer = StudentSerializer(instance=data_all, many=True)
        # 我们用Response直接返回
        # serializer.data: 通常会通过访问序列化器实例的.data属性来获取转换后的数据
        # 因为.data属性包含了序列化后的数据,这些数据已经准备好以适当的格式(如JSON)返回给客户端
        return Response(serializer.data)
    
# 在视图类中查询单个信息,用视图类继承APIView父类
class StudentDetailView(APIView):
    def get(self, request, pk):
        student_obj = Student.objects.filter(pk=pk).first()
        # print(student_obj)
        if not student_obj:
            return HttpResponse("数据不存在!!")
        serializer = StudentSerializer(instance=student_obj)
        return Response(serializer.data)
  • 这里有一个错误,你即使定义好了所有数据,配置好了所有的路径,什么东西都配置好了,但是你在浏览器访问还是会报下面这个错

    • 是因为,我们用的序列化方法也相当于一个APP,所以需要在settings中注册

    • 'rest_framework'

    • 注册好后,你再访问你就可以看到数据了,而且还是好看的页面

【2】常用的字段类

  • 记住一个中要的点:models中的字典的类型,一点要和序列化类里面的字段一一对

  • 实在是记不住:你就把所有的字段类型设置成:CharField

字段字段构造方式
BooleanFieldBooleanField()
NullBooleanFieldNullBooleanField()
CharFieldCharField(max_length=None, min_length=None, allow_blank=False, trim_whitespace=True)
EmailFieldEmailField(max_length=None, min_length=None, allow_blank=False)
RegexFieldRegexField(regex, max_length=None, min_length=None, allow_blank=False)
SlugFieldSlugField(maxlength=50, min_length=None, allow_blank=False) 正则字段,验证正则模式 [a-zA-Z0-9-]+
URLFieldURLField(max_length=200, min_length=None, allow_blank=False)
UUIDFieldUUIDField(format=’hex_verbose’) format: 1) 'hex_verbose'"5ce0e9a5-5ffa-654b-cee0-1238041fb31a" 2) 'hex'"5ce0e9a55ffa654bcee01238041fb31a" 3)'int' - 如: "123456789012312313134124512351145145114" 4)'urn' 如: "urn:uuid:5ce0e9a5-5ffa-654b-cee0-1238041fb31a"
IPAddressFieldIPAddressField(protocol=’both’, unpack_ipv4=False, **options)
IntegerFieldIntegerField(max_value=None, min_value=None)
FloatFieldFloatField(max_value=None, min_value=None)
DecimalFieldDecimalField(max_digits, decimal_places, coerce_to_string=None, max_value=None, min_value=None) max_digits: 最多位数 decimal_palces: 小数点位置
DateTimeFieldDateTimeField(format=api_settings.DATETIME_FORMAT, input_formats=None)
DateFieldDateField(format=api_settings.DATE_FORMAT, input_formats=None)
TimeFieldTimeField(format=api_settings.TIME_FORMAT, input_formats=None)
DurationFieldDurationField()
ChoiceFieldChoiceField(choices) choices与Django的用法相同
MultipleChoiceFieldMultipleChoiceField(choices)
FileFieldFileField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL)
ImageFieldImageField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL)
ListFieldListField(child=, min_length=None, max_length=None)
DictFieldDictField(child=)

【3】常用的字段参数

  • 序列化的字段类在实例化时传递参数的作用是

    • 为了反序列化校验用

  • 我们常用的有哪些字段参数

    • 针对于CharField

      • max_length:最大长度

      • min_length:最小长度

      • allow_blank:是否允许为空

      • trim_whitespace 是否截断两头的空白字符

    • 只针对于:IntegerField

      • max_value:最大值

      • min_value:最小值

    • 只针对于:DateTimeField

      • format:序列化时,显示的格式

        • DateTimeField(format='Y-m-d')

    • 所有字段类都用

      • required:是否必填

      • default:反序列化时使用的默认值

      • allow_null:表明该字段是否允许传入None,默认False

  • 有两个重点后面会将

    • read_only:表明该字段仅用于序列化输出,默认False

    • write_only:表明该字段仅用于反序列化输入,默认False

【五】反序列化保存

【0】步骤

  • 使用序列化类,继承Serializer

  • 在字段类中写字段和字段参数,字段参数是当作校验用的

【1】新增数据

  • 新增数据你需要在你的序列化类里面重写:create方法

from rest_framework import serializers
from app1.models import Student
​
# 定义序列化类,定义的序列化类要与,models里面定义的字段类都对应
class StudentSerializer(serializers.Serializer):
    # 定义的序列化字段的类型也要一样,里面不用写限制条件
    name = serializers.CharField()
    age = serializers.IntegerField()
    gender = serializers.IntegerField()
    # 一定要重写create:不然不会报错
    # 我们可一看到源码中的create什么都没干
    def create(self, validated_data):
        # validated_date:这个数据是前端传入,校验过后的数据
        student = Student.objects.create(**validated_data)
        # 一定要把新增的对象返回出去
        # 因为我们调用serializer.data时,会使用序列化
        return student
  • 在视图类中加上校验规则,然后直接.create保存

from rest_framework.response import Response
from rest_framework.views import APIView
from .serializer import StudentSerializer
​
# 在视图类中查询所有用视图类继承APIView父类
class StudentView(APIView):
    def get(self, request):
        # 这里就简写的get,主要看post
        pass
​
    def post(self, request):
        # 添加数据
        serializer = StudentSerializer(data=request.data)
        # 反序列化校验,保存到数据库
        if serializer.is_valid():
            serializer.save()
            # 序列化对象输出
            # 而是将序列化后的数据作为HTTP响应返回给客户端
            return Response(serializer.data)
        else:
            # 
            return Response({
                "code": 101,
                "msg": "数据校验失败!"
            })

【2】修改数据

  • 修改数据你需要在你的序列化类里面重写:update方法

from rest_framework import serializers
from app1.models import Student

# 定义序列化类,定义的序列化类要与,models里面定义的字段类都对应
class StudentSerializer(serializers.Serializer):
    # 定义的序列化字段的类型也要一样,里面不用写限制条件
    name = serializers.CharField()
    age = serializers.IntegerField()
    gender = serializers.IntegerField()

    def update(self, instance, validated_data):
        """
        :param instance: 等待修改的对象
        :param validated_data: 前端传入校验后的数据
        :return:
        """
        # 第一种方法写
        # instance.name = validated_data.get('name')
        # instance.age = validated_data.get('age')
        # instance.gender = validated_data.get('gender')
        # 方式二
        for key in validated_data:
            # 这个是面向对象的反射方法,向当前对象中设置属性名和属性值
            setattr(instance, key, validated_data[key])
        instance.save()
        return instance
  • 视图类函数

from rest_framework.response import Response
from rest_framework.views import APIView
from .serializer import StudentSerializer
from .models import Student

class StudentDetailView(APIView):
    def put(self, request, pk):
        # 对数据进行替换
        student_obj = Student.objects.filter(pk=pk).first()
        if not student_obj:
            return Response({'code': 101, "mag": "数据不存在!"})
        # instance对应老数据,data对应新数据,进行替换
        serializer = StudentSerializer(instance=student_obj, data=request.data)
        # 反序列化校验,保存到数据库
        if serializer.is_valid():
            # 保存
            serializer.save()
            return Response(serializer.data)
        else:
            return Response({
                "code": 101,
                "msg": "数据校验失败!"
            })

【3】为什么要重写create和update方法

  • 看源码

# 因为你用的seriarlizer.save,会触发self.create或self.update执行
# 我们没有写过,就要去父类里面找,父类里面没找到,找父类的父类,找到了
# 我们可以看到create方法和update方法什么也没做,我们没有重写这个方法的时候报的就是这个错
def create(self, validated_data):
    raise NotImplementedError('`create()` must be implemented.')
​
def update(self, instance, validated_data):
    raise NotImplementedError('`update()` must be implemented.')
  • 现在问题来了

    • 我们明明调用的都是save,为什么会执行create和update方法呢

    • 而且我们也没有写save这个方法,就要去父类里面找,父类里面没找到,找父类的父类,找到了

    • 看源码

     
   # 这个self是我们自己序列化类的对象
        # 我们一看到,如果是修改的时候instance是不能等于None的
        if self.instance is not None:
            # 这里=self.update()我们自己重写了,调用的我们自己的
            self.instance = self.update(self.instance, validated_data)
​
        else:
            # 如果self.instance没值,他就是添加数据
            self.instance = self.create(validated_data)
        return self.instance

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值