Django Rest Framework 序列化介绍以及应用
Django自身的两种序列化方法
- 前后端分离中的序列化介绍:
前后端交互一般都选择JSON数据格式,JSON是一个轻量级的数据交互格式‘。
所以,后端发往前端的数据都需要转成 json 格式的数据,
转化成json数据就需要进行序列化
- 通过ORM中的values方法获取QuerySet列表后,用json模块序列化:
- 特点: 代码写的较多
# views.py
from django.views import View from django.http import JsonResponse from . import models class TeamView(View): def get(self, request): # 通过values 获取QuerySet对象 team_list = models.Team.objects.all().values() print(team_list, "\n", type(team_list)) # [{'id': 1, 'name': 'Python全栈13期', 'category': 1, 'create_time': datetime.date(2018, 10, 29), 'student_id': 2}, {'id': 2, 'name': 'Linux运维全栈开发50期', 'category': 2, 'create_time': datetime.date(2018, 10, 29), 'student_id': 1}] # 将team_list 转换为list对象,在通过循环,构建一个完整的数据结构 team_list = list(team_list) for item in team_list: # 一对多字段 获取学生信息 student_obj = models.Students.objects.filter(id=item["student_id"]).values() # list() 后给字典重新赋值,通过JsonRespon 直接发送过去 item["student_id"] = list(student_obj) print("team_list改过后:", team_list) return JsonResponse(team_list, safe=False, json_dumps_params={"ensure_ascii": False})
- Django 自带的serializers 自动序列化;
- 特点:序列好的数据 废话太多, 外键关系依然需要自己去构建
from django.views import View from django.http import HttpResponse,JsonResponse # 导入 serializers from django.core import serializers from . import models class TeamView(View): def get(self, request): team_list = models.Team.objects.all() ret = serializers.serialize("json", team_list, ensure_ascii=False) return HttpResponse(ret)
DRF序列化方法
- 安装: pip install djangorestframework
- 官网:https://www.django-rest-framework.org/tutorial/quickstart/
- 使用:
- 在Django项目中注册app:
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'app01.apps.App01Config', # 将 rest_framework 注册在这里 "rest_framework" ]
- 在Views中使用:
- 导入 from rest_framework.views import APIView; CBV类型的视图需要继承 APIView
- 返回的response对象,导入:from rest_framework.response import Response ;利用 Response 来返回response对象
- 导入自定义的序列化器, 并将数据库得到的数据对象传入
- 简单示例:
from rest_framework.views import APIView from rest_framework.response import Response from . import models from . import serializers class TeamView(APIView): def get(self, request): # 获取数据库中的数据 team_obj = models.Team.objects.all() # 将数据传入自定义的序列化器中 ser_obj = serializers.TeamSerializer(team_obj, many=True) # 返回页面 return Response(ser_obj)
序列化器
- 序列化器:DRF里面的序列化的过程,基本上就是在这里面实现的,同样这里面也可以对提交的请求进行校验;
- 定义序列化器:
- 导入 from rest_framework import serializers ;
- 自定义一个类, 继承 serializers.Serializer;
- 声明需要序列化的字段;
- 简单示例:
"""
serializers.py
序列化器 注意: 定义的字段的名字要和获取的数据库的字段保持一致 """ from rest_framework import serializers from . import models class StudentSerializer(serializers.Serializer): id = serializers.IntegerField() name = serializers.CharField(max_length=32) class TeacherSerializer(serializers.Serializer): id = serializers.IntegerField() name = serializers.CharField(max_length=32) class TeamSerializer(serializers.Serializer): id = serializers.IntegerField() name = serializers.CharField(max_length=32) category = serializers.CharField(max_length=32, source="get_category_display") create_time = serializers.DateField() student = StudentSerializer() teacher = TeacherSerializer(many=True)
- 反序列化 以及post请求:
- 有序列化就有反序列化;以post请求为例:(post请求在restful中为增加,刷新数据)
- 定义post方法:
- 获取request中提交的数据: request.data; 和正常django中的request不同,在DRF中post请求数据存放在 data中;
- 将数据传入自定义的序列化器中;
- 校验数据;
- 保存数据;
- obj.save(); 调用的是序列化器中 create方法,所以需要在序列化中重新定义该方法;
- 视图示例:
class TeamView(APIView): def post(self, request): # 获取数据 team_obj = request.data # 传入序列化器中 ser_obj = serializers.TeamSerializer(data=team_obj) # 数据校验 if ser_obj.is_valid(): # 保存数据 ser_obj.save() # 返回JSON return Response(ser_obj.validated_data) # 校验失败,返回错误信息 return Response(ser_obj.errors)
- 序列化器:
- 因为序列化和反序列化接受的数据不同,所以不能走同样的数据,在定义序列化器的时候需要做好区分;
- required:此参数,表示 某字段是否需要校验;
- read_only:此参数,表示 序列化时验证该字段;
- write_only:此参数, 表示 反序列化时验证该字段;
- 示例:
""" 序列化器 """ from rest_framework import serializers from . import models class StudentSerializer(serializers.Serializer): id = serializers.IntegerField() name = serializers.CharField(max_length=32) class TeacherSerializer(serializers.Serializer): id = serializers.IntegerField() name = serializers.CharField(max_length=32) class TeamSerializer(serializers.Serializer): id = serializers.IntegerField(required=False) name = serializers.CharField(max_length=32) category = serializers.CharField(max_length=32, source="get_category_display", read_only=True) create_time = serializers.DateField() student = StudentSerializer(read_only=True) teacher = TeacherSerializer(many=True, read_only=True) category_id =serializers.ChoiceField(choices=((1, "Python"), (2, "Linux"), (3, "Golange")), write_only=True) student_id = serializers.IntegerField(write_only=True) teacher_list = serializers.ListField(write_only=True)
- 重写 create方法:
def create(self, validated_data): """ 若不写create方法,在调用ser_obj.save()时会报错; 注意: * 传送的数据的变量名要前后一致 :param validated_data: 验证通过的数据 :return: """ team_obj = models.Team.objects.create( name=validated_data["name"], category=validated_data["category_id"], create_time=validated_data["create_time"], student_id=validated_data["student_id"], ) team_obj.teacher.add(*validated_data["teacher_list"]) return team_obj
序列化器:ModelSerializer
- ModelSerializer 是经过封装 序列化器,
根据模型自动生成一组字段;
自动为序列化器生成验证器;
包括简单的默认实现 .create()
和 .update()
- 基本使用方法:
- 继承 serializers.ModelSerializer;
- 在类中 定义 Meta 元类;
- 元类中的静态字段:
- 常用字段:
- model:指定关联的Orm的类
- fields:显式设置应序列化的字段列表;或显示所有字段"__all__";
- exclude:要从序列化程序中排除的字段列表;该字段不能和fields同时存在
- read_only_fields:指定设为只读的字段列表,将只在序列化的时候认证;(默认 AutoField为只读字段)
- extra_kwargs:在任意字段上指定任意其他关键字参数
- 其他字段:
- depth:对应的值为一个整数值,该值指示在还原为平面表示之前应该遍历的关系深度
- SerialzerMethodeField :
- 这是一个只读字段。它通过调用附加到的序列化程序类上的方法来获取其值。它可用于将任何类型的数据添加到对象的序列化表示中。
- 语法:SerializerMethodField(method_name=None); methoe_name: 要调用的序列化程序上方法的名称, 默认为 get_字段名;
- 示例:
from rest_framework import serializers from . import models class TeamSerializer(serializers.ModelSerializer): # 这里重新定义字段,会将默认显示的字段进行覆盖; category = serializers.CharField(source="get_category_display") # 自定义显示关联的字段 student_info = serializers.SerializerMethodField() teacher_info = serializers.SerializerMethodField() def get_student_info(self, obj): return { "id": obj.student.id, "name": obj.student.name } def get_teacher_info(self, obj): teacher_obj = obj.teacher.all() ret = [] for teacher in teacher_obj: ret.append({ "id": teacher.id, "name": teacher.name }) return ret class Meta: model = models.Team # fields, exclude 不能同时存在,且必须有一个; fields = "__all__" # exclude = ["create_time"] # depth = 1
- 反序列化相关:
- 与 序列化的关键字区分开;
- 利用 extra_kwargs 字段,给需要返回的字段增加参数write_only=True
extra_kwargs = { "category": {"write_only": True}, "student": {"write_only": True}, "teacher": {"write_only": True}, }