Django序列化和json模块的序列化

从数据库中取出数据后,虽然不能直接将queryset和model对象以及datetime类型序列化,但都可以将其转化成可以序列化的类型,再序列化。

功能需求都能做到,但是比较麻烦,每次需要手动实现。且取出的数据还需要进行转化,比如某些字段在存储时将汉字转化成数字,取出来后要将数字转化成汉字,这都是需要每次手动操作。

Django REST Framework序列化

作用:

  • 对数据库中取出的数据序列化
  • 字段值的转化(包括choice、外键、一对一关系、多对多关系)
  • 字段验证(自动验证和自定义验证)

models.py

  1. class Book(models.Model):
  2. title = models.CharField(max_length=32, verbose_name="图书名称")
  3. CHOICES = ((1, "Python"), (2, "Go"), (3, "Linux"))
  4. category = models.IntegerField(choices=CHOICES, verbose_name="图书的类别")
  5. pub_time = models.DateField(verbose_name="图书的出版日期")
  6.  
  7. publisher = models.ForeignKey(to="Publisher", on_delete=None)
  8. author = models.ManyToManyField(to="Author")
  9.  
  10. def __str__(self):
  11. return self.title
  12.  
  13. class Meta:
  14. verbose_name_plural = "Book"
  15. db_table = verbose_name_plural
  16.  
  17. class Publisher(models.Model):
  18. title = models.CharField(max_length=32, verbose_name="出版社的名称")
  19.  
  20. def __str__(self):
  21. return self.title
  22.  
  23. class Meta:
  24. verbose_name_plural = "Publisher"
  25. db_table = verbose_name_plural
  26.  
  27. class Author(models.Model):
  28. name = models.CharField(max_length=32, verbose_name="作者的姓名")
  29.  
  30. def __str__(self):
  31. return self.name
  32.  
  33. class Meta:
  34. verbose_name_plural = "Author"
  35. db_table = verbose_name_plural

serializers.Serializer序列化

views.py

  1. from .seriallzers import BookSeriallzer # 自定义的问加减
  2.  
  3. class BookView(APIView):
  4.  
  5. def get(self, request):
  6. book_list = Book.objects.all()
  7. ret = BookSeriallzer(book_list, many=True) # 序列化过程
  8. return Response(ret.data)
  9.  
  10. def post(self, request):
  11. print("数据",request.data)
  12. serializer = BookSeriallzer(data=request.data) # 反序列化
  13. if serializer.is_valid():
  14. print("验证通过")
  15. serializer.save() # save()方法保存数据库,需要在序列化器里自定义create方法
  16. return Response(serializer.data)
  17. else:
  18. return Response(serializer.errors)

seriallzers.py

  1. from rest_framework import serializers
  2.  
  3. def my_validate(value):
  4. if "mingan" in value.lower():
  5. raise serializers.ValidationError("不能含有敏感信息")
  6. else:
  7. return value
  8.  
  9. class BookSeriallzer(serializers.Serializer):
  10. id = serializers.IntegerField(required=False) # required False的意思是 反序列化(存库)的时候非必需
  11. title = serializers.CharField(max_length=32, validators=[my_validate]) # 此种验证方式比局部钩子优先级高
  12. CHOICES = ((1, "Python"), (2, "Go"), (3, "Linux"))
  13. category = serializers.ChoiceField(choices=CHOICES, source="get_category_display", read_only=True) # 只在序列化(读库)的时候起作用
  14. w_category = serializers.ChoiceField(choices=CHOICES, write_only=True) # 只在反序列化的时候用(存库)
  15. pub_time = serializers.DateField()
  16.  
  17. publisher = PublishSeriallzer(read_only=True)
  18. publisher_id = serializers.IntegerField(write_only=True)
  19.  
  20. author = AuthorSeriallzer(many=True, read_only=True) # 通过many参数来区别是普通外键还是多对多关系
  21. author_list = serializers.ListField(write_only=True)
  22.  
  23. def create(self, validated_data):
  24. book = Book.objects.create(title=validated_data["title"],category=validated_data["w_category"],
  25. pub_time=validated_data["pub_time"], publisher_id=validated_data["publisher_id"])
  26. book.author.add(*validated_data["author_list"])
  27. return book
  28.  
  29. def update(self, instance, validated_data):
  30. "instance是views函数中传来的book_obj"
  31. instance.title = validated_data.get("title", instance.title) # 如果已验证的数据中没有title字段,不更新,不会报错
  32. instance.category = validated_data.get("w_category", instance.category)
  33. instance.pub_time = validated_data.get("pub_time", instance.pub_time)
  34. instance.publisher_id = validated_data.get("publisher_id", instance.publisher_id)
  35. if validated_data.get("author_list"):
  36. instance.author.set(validated_data["author_list"]) # 更新多对多字段
  37. instance.save()
  38. return instance
  39.  
  40. def validate_title(self, value):
  41. "局部钩子,自定义对title字段的验证"
  42. if "python" not in value.lower():
  43. raise serializers.ValidationError("标题必须含有python")
  44. return value
  45.  
  46. def validate(self, attrs):
  47. "全局的校验规则,可以进行多字段联合校验"
  48. if attrs["w_category"] == 1 and attrs["publisher_id"] == 1:
  49. return attrs
  50. else:
  51. raise serializers.ValidationError("分类以及标题不符合要求")
  52. 验证顺序:validators属性 -> 局部钩子 -> 全局钩子

这样就实现了 序列化 和 反序列化的过程,包括特殊字段(时间类型、外键关系、chioce)转化以及存库时的验证。

需要说明的是:

  • choice字段、外键由于存取的需求不一致(存数字,取汉字、外键对应的其它字段),需要将序列化和反序列化的过程区分开来,分成两个变量名。用read_only和write_only区分
  • 验证发生在反序列化的过程(存库),会自动验证字段类型、必填属性、长度等条件。
  • 自定义验证有三种方式,要注意先后顺序。

但是,序列化和反序列化的过程非常不简洁,写了太多的东西。

serializers.ModelSerializer序列化

ModelSerializer类可以与ORM映射表结合,自动对应序列化关系。

  1. from .models import Book, Publisher
  2.  
  3. class BookSeriallzer(serializers.ModelSerializer):
  4. category_display = serializers.SerializerMethodField() # 读取数据时的字段名(与"category"区分开来,下同)
  5. publisher_info = serializers.SerializerMethodField() # 配合 get_字段名() 钩子,自定义通过外键取出的字段
  6. authors = serializers.SerializerMethodField()
  7.  
  8. def get_category_display(self, obj):
  9. return obj.get_category_display()
  10.  
  11. def get_publisher_info(self, obj):
  12. # obj 是每个book对象
  13. publisher_obj = obj.publisher
  14. return {"id": publisher_obj.id, "title": publisher_obj.title} # 只取出来自己想要的数据,不会有其他的冗余数据
  15.  
  16. def get_authors(self, obj):
  17. authors = obj.author.all()
  18. return [{"id": author.id, "name": author.name} for author in authors]
  19.  
  20. class Meta:
  21. model = Book # 对应ORM表
  22. # fields = ["id", "title", "pub_time", "category"] # 需要取出的字段
  23. fields = "__all__" # 表示要取出所有字段
  24. # depth = 1 # 序列化的外键层级。如果不规定此值,所有的外键字段都只是id。有个缺点:会取出外键对应的所有数据,非常冗余
  25. extra_kwargs = {
  26. "category": {"write_only": True}, # “category”字段只写
  27. "publisher": {"write_only": True},
  28. "author": {"write_only": True}
  29. }

这样,我们只需要将存取不一致的行为定义好即可,其它字段都可以自动对应好。非常方便。

Django REST Framework序列化器的更多相关文章

  1. [Django REST framework - 序列化组件、source、钩子函数]

    [Django REST framework - 序列化组件.source.钩子函数] 序列化器-Serializer 什么是rest_framework序列化? 在写前后端不分离的项目时: 我们有f ...

  2. Django REST framework - 解析器和渲染器

    目录 Django REST framework - 解析器和渲染器 解析器 Django中的数据解析 DRF中的解析器 渲染器 Django REST framework - 解析器和渲染器 解析器 ...

  3. Django 学习之Django Rest Framework_序列化器_Serializer

    作用: 1.序列化,序列化器会把模型对象转换成字典,经过response以后变成json字符串. 2.反序列化,把客户端发送过来的数据,经过request以后变成字典,序列化器可以把字典转成模型. 3 ...

  4. Django REST framework序列化

    一.简介 Django REST framework是基于Django实现的一个RESTful风格API框架,能够帮助我们快速开发RESTful风格的API. 官网:https://www.djang ...

  5. Django REST Framework 序列化和校验 知识点

    DRF序列化 Django ORM对象 --> JSON格式的数据 序列化 JSON格式的数据 --> Django ORM数据 反序列化 需要两个工具: from rest_framew ...

  6. Django Rest framework序列化流程

    目录 一 什么是序列化 二 Django REST framework配置流程之Serializer 三 Django REST framework配置流程之ModelSerializer 一 什么是 ...

  7. Django:RestFramework之-------序列化器

    8.序列化 功能: 对请求数据进行验证 对Queryset进行序列化 8.1一个简单序列化: import json from api import models from rest_framewor ...

  8. django rest framework 解析器组件 接口设计,视图组件 (1)

    一.解析器组件 -解析器组件是用来解析用户请求数据的(application/json), content-type 将客户端发来的json数据进行解析 -必须适应APIView -request.d ...

  9. 02 Django REST Framework 序列化

    01-创建序列化类 # 方式一: publish_list = models.Publish.objects.all() # 导入序列化组件 from django.core import seria ...

随机推荐

  1. MongoDB 数据库的学习与使用

    MongoDB 数据库 一.MongoDB 简介(了解) ​ MongoDB 数据库是一种 NOSQL 数据库,NOSQL 数据库不是这几年才有的,从数据库的初期发展就以及存在了 NOSQL 数据库. ...

  2. 开发人员需要掌握的日常Linux命令集

    本文整理了开发人员日常用到的linux相关命令,供参考. 文件相关 cd # 进入某个目录,不接参数进入当前用户目录(等同于cd ~)如/home/devuser,可接绝对路径或相对路径(../..表 ...

  3. Java 从入门到进阶之路(四)

    之前的文章我们介绍了 Java 的运算符和表达式,本章我们来看一下 Java 的循环结构. 循环是程序设计语言中反复执行某些代码的一种计算机处理过程,是一组相同或相似语句被有规律的重复性进行. 循环的 ...

  4. SQL优化没思路,智能优化工具来帮你

    前言 作为DBA或系统管理员,我们有时会遇到一个慢SQL需要优化,但是通过分析执行计划又没有找到好的优化思路,或者优化之后效果不明显,没有达到自己理想的预期,此时的你是不是很焦虑?此时你一定想如果有一 ...

  5. 【入门】广电行业DNS、DHCP解决方案详解(一)——历史及现状篇

    广电发展历史 单项网络 双向网络 智能网络 广电网络现状 广电网络典型特征 接入技术混杂 承载业务多样化 业务终端错综复杂 其他 网络现状模型 总结 广电发展历史 广电就是广播电视,广电发展可以分为三 ...

  6. jvm系列(五):Java GC 分析

    Java GC就是JVM记录仪,书画了JVM各个分区的表演. 什么是 Java GC Java GC(Garbage Collection,垃圾收集,垃圾回收)机制,是Java与C++/C的主要区别之 ...

  7. Unity官方案例精讲_2015_优化

    1.将公共变量从Inspector视图中隐藏:    [HideInInspector] [HideInInspector] public GameObject player; 2.限定Inspect ...

  8. .NET Core ASP.NET Core Basic 1-2 控制反转与依赖注入

    .NET Core ASP.NET Core Basic 1-2 本节内容为控制反转与依赖注入 简介 控制反转IOC 这个内容事实上在我们的C#高级篇就已经有所讲解,控制反转是一种设计模式,你可以这样 ...

  9. sql建表经验总结——主要是建表现象

    在建表方面你都有哪些感悟? 见过的建表的一些现象: 1,一对多业务,有时候在主表见一个字段xxIds,然后存多表的id,多个英文逗号隔开,不知道这样好不好? 2,大部分字段建成varchar(50), ...

  10. JDK中的Proxy技术实现AOP功能

    1.需求,用户在执行某个业务方法时我们需要对这个用户进行判断是否具有权限(或者说用户是否登录了)? 例如修改用户信息,我们在update()方法前判断当前用户user是否为null(表示没有权限或者没 ...