Django 原生 serializer (序列化)
导入模块 from django.core.serializers import serialize
获取 queryset
对 queryset 进行序列化
将序列化之后的数据, 返回给客户端
首先, 设计 url, 先只定义 GET 和 POST 接口
- from django.urls import path
- from DrfOne import views
- urlpatterns = [
- path('books/', views.BookView.as_view()),
- ]
再定义几个 models
- from django.db import models
- class Publish(models.Model):
- nid = models.AutoField(primary_key=True)
- name = models.CharField("出版社名", max_length=32)
- address = models.CharField("出版社位置", max_length=32)
- email = models.EmailField("邮箱")
- def __str__(self):
- return self.name
- class Author(models.Model):
- nid = models.AutoField(primary_key=True)
- name = models.CharField("姓名", max_length=31)
- age = models.IntegerField("年龄")
- def __str__(self):
- return self.name
- class Book(models.Model):
- nid = models.AutoField(primary_key=True)
- title = models.CharField("书名", max_length=32)
- price = models.DecimalField("价格", max_digits=5, decimal_places=2)
- publish = models.ForeignKey(to="Publish", on_delete=models.CASCADE)
- authors = models.ManyToManyField(to="Author")
- def __str__(self):
- return self.title
models.py
使用
- from django.shortcuts import render, HttpResponse
- from rest_framework.views import APIView
- # 1. 导入模块
- from django.core.serializers import serialize
- class CourseView(APIView):
- def get(self, request):
- # 2. 获取 queryset
- course_obj = models.Course.objects.all()
- # 3. 序列化
- serialized_data = serialize("json", course_obj)
- print(serialized_data)
- # 4. 将序列化之后的数据返回
- return HttpResponse(serialized_data)
序列化组件 serializer 的使用
Serializer
GET 接口设计 (获取所有数据)
导入模块
建立一个序列化类
获取 queryset
开始序列化
获取序列化后的数据, 返回给客户端
- from rest_framework.views import APIView
- # 1. 导入模块
- from rest_framework import serializers
- # drf 重新封装之后的 Response 基于 TemplateResponse 类型,
- # 可以将未处理的内容通过内容协商来决定返回给客户端的正确内容形式
- from rest_framework.response import Response
- from DrfOne import models
- # 2. 创建一个序列化类, 字段名和字段类型不一定要跟 models 的字段一样
- class BookSerializer(serializers.Serializer):
- # id 一般情况不用写
- # nid = serializers.CharField(max_length=32)
- title = serializers.CharField(max_length=32)
- price = serializers.DecimalField(max_digits=5, decimal_places=2)
- # 外键字段, 显示__str__方法的返回值
- publish = serializers.CharField()
- # 多对多字段, 执行 get_字段名 方法, 手动获取数据
- author_list = serializers.SerializerMethodField()
- def get_author_list(self, book_obj):
- # 第二个参数随意
- author_list = list()
- for author in book_obj.authors.all():
- author_list.append(author.name)
- return author_list
- class BookView1(APIView):
- def get(self, request):
- # 3. 获取 queryset
- book_objs = models.Book.objects.all()
- # 4. 通过序列化类进行序列化
- serialized_obj = BookSerializer(book_objs, many=True)
- # print(serialized_obj)
- # 5. 获取序列化之后的数据, 返回给客户端
- return Response(serialized_obj.data)
POST 接口设计
导入模块
建立一个序列化类
获取客户端请求数据
开始序列化
写入数据库
将插入的对象返回给客户端
请注意, 因为多对多关系字段是我们自定义的, 而且必须这样定义, 返回的数据才有意义, 而用户插入数据的时候, serializers.Serializer 没有实现 create, 我们必须手动插入数据, 就像这样:
- # 1. 导入模块
- from rest_framework import serializers
- from rest_framework.views import APIView
- # drf 重新封装之后的 Response 基于 TemplateResponse 类型,
- # 可以将未处理的内容通过内容协商来决定返回给客户端的正确内容形式
- from rest_framework.response import Response
- from DrfOne import models
- # 2. 创建一个序列化类, 字段名和字段类型不一定要跟 models 的字段一样
- class BookSerializer(serializers.Serializer):
- # id 一般情况不用写
- # nid = serializers.CharField(max_length=32)
- title = serializers.CharField(max_length=32)
- price = serializers.DecimalField(max_digits=5, decimal_places=2)
- # 外键字段, 显示__str__方法的返回值
- publish = serializers.CharField()
- # 仅读字段 read_only=True,source 是该字段显示出版社地址
- publish_address = serializers.CharField(max_length=32, read_only=True, source="publish.address")
- publish_email = serializers.CharField(max_length=32, read_only=True, source="publish.email")
- # 多对多字段, 执行 get_字段名 方法, 手动获取数据
- author_list = serializers.SerializerMethodField()
- def get_author_list(self, book_obj):
- # 第二个参数随意
- author_list = list()
- for author in book_obj.authors.all():
- author_list.append(author.name)
- return author_list
- def create(self, validated_data):
- # 创建时调用
- validated_data['publish_id'] = validated_data.pop('publish')
- book = models.Book.objects.create(**validated_data)
- return book
- def update(self, instance, validated_data):
- # 更新数据会调用该方法
- instance.title = validated_data.get('title', instance.title)
- instance.publishDate = validated_data.get('publishDate', instance.publishDate)
- instance.price = validated_data.get('price', instance.price)
- instance.publish_id = validated_data.get('publish', instance.publish.nid)
- instance.save()
- return instance
- class BookView(APIView):
- def get(self, request):
- pass
- def post(self, request):
- # 3. 获取客户端的数据
- client_data = request.data
- # 4. 序列化, 默认 many=False 单条数据
- verified_data = BookSerializer(data=client_data)
- # 对数据进行验证
- if verified_data.is_valid():
- # 5. 写入数据库
- book = verified_data.save()
- authors = models.Author.objects.filter(nid__in=request.data["authors"])
- book.authors.add(*authors)
- # 6. 将插入的对象数据返回
- return Response(verified_data.data)
- # 验证失败返回错误信息
- return Response(verified_data.errors)
从上面可以看出:
serializers.Serializer 无法插入数据, 只能自己实现.
字段太多, 不能自动序列化
这样就会非常复杂化程序, 如果我希望序列化类自动插入数据呢?
这也就有了 ModelSerializer
ModelSerializer
ModelSerializer 类似于 form 组件里的 ModelForm
- from rest_framework import serializers
- from rest_framework.views import APIView
- class BookSerializer(serializers.ModelSerializer):
- class Meta:
- model = models.Book
- fields = "__all__"
- extra_kwargs = {
- # 仅写
- "publish": {'write_only': True},
- "authors": {'write_only': True},
- }
- publish_name = serializers.CharField(max_length=32, read_only=True, source="publish.name")
- publish_address = serializers.CharField(max_length=32, read_only=True, source="publish.address")
- author_name = serializers.SerializerMethodField()
- def get_author_name(self, book_obj):
- author_list = list()
- for author in book_obj.authors.all():
- # 注意列表添加字段, author.name 而不是 author
- author_list.append(author.name)
- return author_list
这样看起来简单多了!
get(单条数据),put(改),delete(删) 接口设计
设计 url
- from django.urls import path, re_path
- from DrfOne import views
- urlpatterns = [
- path('books/', views.BookView.as_view()),
- re_path("books/(\d+)/", views.BookFilterView.as_view()),
- ]
视图设计
- class BookFilterView(APIView):
- def get(self, request, nid):
- # 获取 queryset
- book_obj = models.Book.objects.get(pk=nid)
- # 序列化
- serialized_data = BookSerializer(book_obj)
- # 返回数据
- return Response(serialized_data.data)
- def put(self, request, nid):
- # 获取 queryset
- book_obj = models.Book.objects.get(pk=nid)
- # 序列化, 根据 instance 是确认是否是更新, many 默认为 False 可以不写
- verified_data = BookSerializer(data=request.data, instance=book_obj, many=False)
- if verified_data.is_valid():
- verified_data.save()
- # 返回数据
- return Response(verified_data.data)
- return Response(verified_data.errors)
- def delete(self, request, nid):
- models.Book.objects.get(pk=nid).delete()
- return Response("")
- ~>.<~
来源: https://www.cnblogs.com/pungchur/p/12022990.html