前提准备
首先准备几张表,以图书为例,创建图书表,作者表,出版社表和第三张关系表。然后创建一个serializer.py文件,目的就是写类,继承serializer。分发路由。
创建表
class Book(models.Model):
name = models.CharField(max_length=32)
price = models.DecimalField(max_digits=5,decimal_places=2)
publish_date = models.DateTimeField()
publish = models.ForeignKey(to='Publish', on_delete=models.CASCADE)
authors = models.ManyToManyField(to='Author')
def __str__(self):
return self.name
class Author(models.Model):
name = models.CharField(max_length=32)
age = models.IntegerField()
class Publish(models.Model):
name = models.CharField(max_length=32)
city = models.CharField(max_length=32)
email = models.EmailField()
创建serializer.py文件
略。。。
定制返回格式之source
source是一个序列化器的字段选项,用于指定序列化器中字段的源。
总结:
- source定制返回字段名,跟字段必须对应
- 可以跨表查询
ps小知识:所有字段都可以被转成CharField格式。
当我们想要在后期实现下面格式的数据:
{name:书名,price:价格,publish:{name:出版社名,addr:地址},authors:[{},{}]}
那我们该如何做呢?
定制返回字段
方法一:在表模型中写方法,然后在序列化类中做映射
models.py:
serializer.py
效果:
SerializerMethodField字段
方法二:通过SerializerMethodField方法实现:
只需要将后面的字段参数改为SerialzierMethodField字段,然后定义函数返回就可以了。
models.py:
serializer.py
子序列化
方法三:子序列化
反序列化保存
介绍两个字段:
- read_only (仅序列化)
- write_only (仅反序列化)
总结:
- 反序列化字段可以随意命名,与表字段无关,但是后续保存和修改要对应好。
- 需要重写updata和create,保存逻辑需要自己写。
view.py
from rest_framework.views import APIView
# Create your views here.
from .models import Book
from .serializer import BookSerializer
from rest_framework.response import Response
class BookView(APIView):
# 查询所有
def get(self, request):
obj_list = Book.objects.all()
serializer = BookSerializer(instance=obj_list, many=True)
return Response(serializer.data)
def post(self, request):
serializer = BookSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response('添加成功')
else:
return Response({'code':100, 'msg':serializer.errors})
class BookDetailView(APIView):
# 查询单条
def get(self, request, pk):
obj = Book.objects.all().filter(pk=pk).first()
serializer = BookSerializer(instance=obj)
return Response(serializer.data)
def delete(self, request, pk):
Book.objects.filter(pk=pk).first().delete()
return Response('删除成功')
def put(self, request, pk):
# obj = Book.objects.all().filter(pk=pk).first()
serializer = BookSerializer(instance=pk,data=request.data)
if serializer.is_valid():
return Response('修改成功')
else:
return Response({'code': 100, 'msg': serializer.errors})
serializer.py
from rest_framework import serializers
from .models import Book
# class BookSerializer(serializers.Serializer):
# # source 定制返回字段名,跟name 必须对应
# name = serializers.CharField(source='name')
# # 显示出版社名字是字符串类型-->可以跨表查询
# publish_name = serializers.CharField(source='publish.name')
# publish_id = serializers.IntegerField(source='publish.id')
# price = serializers.DecimalField(max_digits=5,decimal_places=2)
# publish_date = serializers.DateTimeField()
# class BookSerializer(serializers.Serializer):
# book_name = serializers.SerializerMethodField()
# def get_book_name(self, obj):
# return obj.name
# price = serializers.DecimalField(max_digits=5, decimal_places=2)
# publish_date = serializers.DateTimeField()
# # 出版社对象
# publish_detail = serializers.SerializerMethodField()
# # 配合一个方法,必须要get_字段名
# def get_publish_detail(self, obj):
# return {'name': obj.publish.name, 'city': obj.publish.city, 'id': obj.pk}
# # 所有作者
# authors_list = serializers.SerializerMethodField()
# def get_authors_list(self, obj):
# l = []
# for author in obj.authors.all():
# l.append({'name': author.name, 'age': author.age, 'id': author.id})
# return l
class PublishSerializer(serializers.Serializer):
id = serializers.IntegerField()
name = serializers.CharField()
city = serializers.CharField()
email = serializers.EmailField()
class AuthorSerializer(serializers.Serializer):
id = serializers.IntegerField()
name = serializers.CharField()
age = serializers.CharField()
from datetime import datetime
class BookSerializer(serializers.Serializer):
name = serializers.CharField()
price = serializers.DecimalField(max_digits=5, decimal_places=2)
publish_date = serializers.DateTimeField(required=False, default=datetime.now)
# 这个字段仅序列化
publish_detail = PublishSerializer(source='publish',read_only=True)
# 这个字段仅序列化
authors_list = AuthorSerializer(source='authors', many=True, read_only=True)
# 反序列化(如果是多表关联)
publish = serializers.IntegerField(write_only=True) # 前端传入数字,自动跟出版社对应
authors = serializers.ListField(write_only=True)
def create(self, validated_data):
publish_id = validated_data.pop('publish')
authors = validated_data.pop('authors')
book = Book.objects.create(**validated_data, publish_id=publish_id)
book.authors.add(*authors)
return book
def update(self, instance, validated_data):
publish_id = validated_data.pop('publish')
authors = validated_data.pop('authors')
book_qs = Book.objects.filter(pk=instance)# 查询qs对象
book_qs.update(**validated_data, publish_id=publish_id) # 使用qs更新
instance = book_qs.first() # 查单个对象
instance.authors.set(authors) # 向中间表中插入数据
return instance
ModelSerializer使用
在之前写序列化类,没有显示指明跟哪个表一一对应,ModelSerializer可以和表做一一对应关系。
如图,这样可以省去很多代码,但是如果想要额外加一些字段,如下操作(仅序列化除外):
仅序列化需要在与class Meta同级下额外添加字段,而class Meta相当于drf自动帮你写好了那些基本字段。
总结:
- ModelSerializer可以和表做一一对应关系
- 局部钩子全局钩子和之前一样写(注意层级)