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},
        }
posted @ 2018-10-29 19:17  浮生凉年  阅读(459)  评论(0编辑  收藏  举报