心蓝的博客 心蓝的博客
首页
  • 零基础

    • python零基础入门
  • 专项

    • 正则表达式
  • web框架

    • django框架
    • drf
技术
  • 友情链接
关于
收藏
  • 分类
  • 标签
  • 归档

心蓝

人生苦短,我用python
首页
  • 零基础

    • python零基础入门
  • 专项

    • 正则表达式
  • web框架

    • django框架
    • drf
技术
  • 友情链接
关于
收藏
  • 分类
  • 标签
  • 归档
  • 零基础

  • 专项

  • web框架

    • django框架

    • drf

      • 简介
      • 序列化器
        • 定义序列化器
        • 使用序列化器
          • 序列化
          • 反序列化
        • 使用模型序列化器
        • 使用序列化器编写普通的Django视图
      • 请求和响应
      • 类视图
      • 视图集和路由器
      • 序列化器补充
      • 身份验证与权限
      • 分页与限流
  • python
  • web框架
  • drf
心蓝
2022-12-26
目录

序列化器

# 序列化器

REST framework的核心就是序列化器。

它提供了一个serializer类,它可以非常方便的序列化模型实例和查询集为JSON或者其他内容的形式。

它还提供反序列化功能,允许在验证传入的数据后将其转换为复杂类型。

# 定义序列化器

接django框架部分的crm案例,在crm应用目录下创建serializers.py文件,编写代码如下:

from rest_framework import serializers

from crm.models import Student


class StudentSerializer(serializers.Serializer):
    """
    学生序列化器
    """
    id = serializers.IntegerField(label='学生id', read_only=True)
    name = serializers.CharField(label='姓名')
    sex = serializers.IntegerField(label='性别', default=1)
    age = serializers.IntegerField(label='年龄', required=False, allow_null=True)
    qq = serializers.CharField(label='qq号码', required=False, allow_null=True)
    phone = serializers.CharField(label='手机号码', required=False, allow_null=True)
    channel = serializers.CharField(label='渠道', read_only=True)
    c_time = serializers.DateTimeField(label='创建时间', read_only=True)

    def create(self, validated_data):
        """
        创建对象
        :param validated_data:
        :return:
        """
        return Student.objects.create(**validated_data)
    
    def update(self, instance, validated_data):
        """
        更新对象
        :param instance: 
        :param validated_data: 
        :return: 
        """
        for key, value in validated_data.items():
            setattr(instance, key, value)
        
        instance.save()
        return instance
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

序列化器类的第一部分定义了要序列化/反序列化的字段。create()和update()方法定义了在调用serializer.save()时如何创建或修改实例。

# 使用序列化器

# 序列化

进入Django Shell

python manage.py shell
1

先导入一些需要用到的对象

from crm.models import Student
from crm.serializers import StudentSerializer
from rest_framework.renderers import JSONRenderer
from rest_framework.parsers import JSONParser

obj = Student.objects.first()
1
2
3
4
5
6

序列化这个实例

s = StudentSerializer(obj)
s.data
# {'id': 3, 'name': '赵六', 'sex': 1, 'age': 22, 'qq': '1111', 'phone': '18684720553', 'channel': '抖音', 'c_time': '2022-01-14T21:45:06.037745+08:00'}
1
2
3

我们已经将模型实例转换为Python原生数据类型。为了完成序列化过程,我们将数据呈现为json。

JSONRenderer().render(s.data)
# b'{"id":3,"name":"\xe8\xb5\xb5\xe5\x85\xad","sex":1,"age":22,"qq":"1111","phone":"18684720553","channel":"\xe6\x8a\x96\xe9\x9f\xb3","c_time":"2022-01-14T21:45:06.037745+08:00"}'
1
2

我们还可以序列化查询集而不只是模型实例,序列化时,再传入参数many=True.

ss = StudentSerializer(Student.objects.all(), many=True)
ss.data
# [OrderedDict([('id', 3), ('name', '赵六'), ('sex', 1), ('age', 22), ('qq', '1111'), ('phone', '18684720553'), ('channel', '抖音'), ('c_time', '2022-01-14T21:45:06.037745+08:00')]), OrderedDict([('id', 15), ('name', '心蓝'), ('sex', 1), ('age', 20), ('qq', '111'), ('phone', '1111123'), ('channel', '百度'), ('c_time', '2022-02-08T21:59:54.743096+08:00')]), OrderedDict([('id', 21), ('name', '西瓜'), ('sex', 1), ('age', 20), ('qq', '123456789'), ('phone', '987654321'), ('channel', '抖音'), ('c_time', '2022-02-09T21:15:37.199509+08:00')])]
1
2
3

# 反序列化

反序列化是相似的,首先将序列化数据(json)解析为原生python数据类型(省略),然后将其填充到一个序列器对象中。

data = {
    "name": "心蓝",
    "sex": 1,
    "age": 18,
    "qq": "123123",
    "phone": "13888888888"
}
s = StudentSerializer(data=data)
s.is_valid()  # 校验
# True
s.validated_data  # 校验后的数据
# OrderedDict([('name', '心蓝'), ('sex', 1), ('age', 18), ('qq', '123123'), ('phone', '13888888888')])
s.save() # 创建对象
# <Student: 心蓝>
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 使用模型序列化器

上面的StudentSerializer类复制了大量Student模型中的的信息。RESTframework提供了一个ModelSerializer,它可以根据模型自动创建Serializer类,代码更简洁。

再次打开crm/serializers.py模块,并用以下代码替换StudentSerializer类。

class StudentSerializer(serializers.ModelSerializer):
    class Meta:
        model = Student
        fields = ['id', 'name', 'sex', 'age', 'phone', 'qq', 'c_time']
1
2
3
4

序列化器的一个很好的属性是,可以通过打印序列化器实例的表示形式来检查它的所有字段。

进入Django shell然后尝试如下操作:

In [1]: from crm.serializers import StudentSerializer
In [2]: s = StudentSerializer()
In [3]: print(s)
StudentSerializer():
    id = IntegerField(label='ID', read_only=True)
    name = CharField(help_text='姓名', label='姓名', max_length=20)
    age = IntegerField(allow_null=True, help_text='年龄', label='年龄', max_value=32767, min_value=-32768, required=False)
    sex = IntegerField(help_text='性别', label='性别', max_value=32767, min_value=-32768, required=False)
    qq = CharField(allow_blank=True, allow_null=True, help_text='qq号码', label='Qq号码', max_length=20, required=False, validators=[<UniqueValidator(queryset=Student.objects.all())>])
    phone = CharField(allow_blank=True, allow_null=True, help_text='手机号码', label='手机号码', max_length=20, required=False, validators=[<UniqueValidator(queryset=Student.objects.all())>])
    c_time = DateTimeField(label='创建时间', read_only=True)
    channel = PrimaryKeyRelatedField(allow_null=True, help_text='渠道来源', label='渠道', queryset=Channel.objects.all(), required=False)
1
2
3
4
5
6
7
8
9
10
11
12

ModelSerializer类并没有做什么特别神奇的事情,它们只是创建序列化器类的一个快捷方式:

  • 一组自动确定的字段。
  • create()和update()方法的简单默认实现。

# 使用序列化器编写普通的Django视图

接下来我们使用新的序列化器来编写一些API视图。当前不使用任何REST framework的其他特性,只写普通的django视图。

编辑crm/views.py添加如下内容:

def student_list(request):
    """
    学生列表,创建学生视图
    :param request:
    :return:
    """
    if request.method == 'GET':
        objs = Student.objects.all()
        # 序列化
        serializer = StudentSerializer(objs, many=True)
        return JsonResponse(serializer.data, safe=False)
    elif request.method == 'POST':
        data = JSONParser().parse(request)
        # 序列化
        serializer = StudentSerializer(data=data)
        if serializer.is_valid():
            serializer.save()
            return JsonResponse(serializer.data, status=201)
        else:
            return JsonResponse(serializer.errors, status=400)


def student_detail(request, pk):
    """
    检索,更新或者删除一个学生
    :param request:
    :param pk:
    :return:
    """
    try:
        obj = Student.objects.get(pk=pk)
    except Student.DoesNotExist:
        return HttpResponse(status=404)
    if request.method == 'GET':
        # 序列化
        serializer = StudentSerializer(obj)
        return JsonResponse(serializer.data)
    elif request.method == 'PUT':
        # 反序列化
        data = JSONParser().parse(request)
        serializer = StudentSerializer(obj, data=data)
        # 校验
        if serializer.is_valid():
            serializer.save()
            return JsonResponse(serializer.data)
        return JsonResponse(serializer.errors, status=400)
    elif request.method == 'DELETE':
        obj.delete()
        return HttpResponse(status=204)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49

路由配置如下:

urlpatterns = [
    path('projects/', views.student_list),
    path('projects/<int:pk>/', views.student_detail)
]
1
2
3
4

那么通过/students/和/students/id/就可以访问对应的接口了。

本文完,感谢你的耐心阅读,如有需要可加我微信,备注「博客」并说明原因,我们一起进步,下次见。

#drf
上次更新: 2022/12/26, 16:59:39
简介
请求和响应

← 简介 请求和响应→

最近更新
01
requests让接口测试如此简单 原创
03-31
02
最简明的python正则教程
03-30
03
pycharm激活码
12-30
更多文章>
Theme by Vdoing | Copyright © 2019-2025 心蓝
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式