序列化的高级用法与ModelSerializer的使用
序列化高级用法之source(了解)
source的三个用法:
1. 取别名:
book_name = serializers.CharField(source='name') # book_name为前端可以看到的字段值,name是对象真实的属性。注意:别名和真实属性不能相同
2. 美化值:
# 写在序列化类中
book_name = serializers.CharField(source='sb_name') # 此时指定的就是方法名
# 写在表模型中
def sb_name(self):
return self.name + '_sb'
3. 关联查询:
publish_name = serializers.CharField(source='publish.name') # 必须有关联关系
序列化高级用法之定制字段的两种方式(非常重要)
# 方式一:在序列化类中写
1 写一个字段,对应的字段类是:SerializerMethodField
2 必须对应一个get_字段名的方法,方法必须接受一个obj,返回什么,这个字段对应的value就是什么
# 方式二:在表模型中写
1 在表模型中写一个方法(可以使用:property),方法有返回值(字典,字符串,列表)
2 在序列化类中,使用DictField,CharField,ListField
序列化类中写
### 定制字段方式1
class BookSerialzier(serializers.Serializer):
name = serializers.CharField()
price = serializers.CharField()
# 拿出出版社的id和名字和addr,放到一个字典中
# 方式一:SerializerMethodField来定制,如果写了这个,必须配合一个方法get_字段名,这个方法返回什么,这个字段的值就是什么
publish_detail = serializers.SerializerMethodField()
def get_publish_detail(self, book):
# print(obj) # 要序列化的book对象
return {'id': book.publish.pk, 'name': book.publish.name, 'addr': book.publish.addr}
# 练习:拿出所有作者的信息--》多条 [{name:,phone:},{}]
author_list = serializers.SerializerMethodField()
def get_author_list(self, book):
l = []
for author in book.authors.all():
l.append({'id': author.pk, 'name': author.name, 'phone': author.phone, 'age': author.author_detail.age})
return l
表模型中写
# 定制字段方式2
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
fields = ['title', 'price', 'publish_detail', 'author_list', 'publish', 'author']
extra_kwargs = {
'title': {'max_length': 8},
'publish': {'write_only': True},
'author': {'write_only': True},
}
# 写在序列化类中
# 在序列化中叫什么在表模型中也要交什么
publish_detail = serializers.DictField(read_only=True)
author_list = serializers.ListField(read_only=True)
# 写在表模型中
@property
def publish_detail(self):
return {'id': self.publish.pk, 'name': self.publish.name, 'addr': self.publish.addr} # 方法返回的是什么字段的value就是什么
@property
def author_list(self):
lis = []
for i in self.author.all():
lis.append({'id': i.pk, 'name': i.name, 'phone': i.phone})
return lis
多表关联反序列化保存
# 序列化和反序列化,用的同一个序列化类
-序列化的字段有:name,price , publish_detail,author_list
-反序列化字段:name,price ,publish,author
反序列化之保存
视图类
class BookView(APIView):
def post(self, request):
ser = BookSerializer(data=request.data)
if ser.is_valid():
ser.save()
return Response({'code': 200, 'msg': '添加成功'})
else:
return Response({'code': 201, 'msg': ser.errors})
序列化类
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
fields = ['title', 'price', 'publish_detail', 'author_list', 'publish', 'author']
extra_kwargs = {
'title': {'max_length': 8}, # 这种可序列化也可反序列化
'publish': {'write_only': True}, # 这俩只用来反序列化
'author': {'write_only': True},
}
publish_detail = serializers.DictField(read_only=True) # 这俩只用来序列化
author_list = serializers.ListField(read_only=True)
反序列化之修改
视图类
class BookDetailView(APIView):
def put(self, request, pk):
book = Book.objects.filter(pk=pk).first()
ser = BookSerializer(instance=book, data=request.data)
if ser.is_valid():
ser.save()
return Response({'code': 200, 'msg': '修改成功'})
else:
return Response({'code': 201, 'msg': ser.errors})
序列化类
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
fields = ['title', 'price', 'publish_detail', 'author_list', 'publish', 'author']
extra_kwargs = {
'title': {'max_length': 8}, # 这种可序列化也可反序列化
'publish': {'write_only': True}, # 这俩只用来反序列化
'author': {'write_only': True},
}
publish_detail = serializers.DictField(read_only=True) # 这俩只用来序列化
author_list = serializers.ListField(read_only=True)
反序列化字段校验其他
# 视图类中调用:ser.is_valid()---》触发数据的校验
-4层
-字段自己的:max_length,required。。。
-字段自己的:配合一个函数name = serializers.CharField(max_length=8,validators=[xxx])
-局部钩子
-全局钩子
ModelSerializer使用
# 之前学的继承Serializer得序列化类,与表模型没有必然的联系,既可序列化A类又可序列化B类
# 现在学的继承了ModelSerialize的序列化类是与表模型一一对应的,用法基本一致
1 写序列化类,继承ModelSerializer
2 在序列化类中,再写一个类,必须叫
class Meta:
model=表模型
fields=[] # 要序列化的字段
3 可以重写字段,一定不要放在class Meta的下面
-定制字段,跟之前讲的一样
4 自定制的字段,一定要在fields中注册一下
5 class Meta: 有个extra_kwargs,为某个字段定制字段参数
6 局部钩子,全局钩子,完全一致
7 大部分请情况下,不需要重写 create和update了
Book的5个接口
表模型
class Book(models.Model):
title = models.CharField(max_length=32)
price = models.IntegerField()
publish = models.ForeignKey(to='Publish', on_delete=models.SET_NULL, null=True)
author = models.ManyToManyField(to='Author')
@property
def publish_detail(self):
return {'id': self.publish.pk, 'name': self.publish.name, 'addr': self.publish.addr}
@property
def author_list(self):
lis = []
for i in self.author.all():
lis.append({'id': i.pk, 'name': i.name, 'phone': i.phone})
return lis
视图类
class BookView(APIView):
def get(self, request):
book = Book.objects.all()
ser = BookSerializer(instance=book, many=True)
return Response({'code': 200, 'msg': '成功', 'data': ser.data})
def post(self, request):
ser = BookSerializer(data=request.data)
if ser.is_valid():
ser.save()
return Response({'code': 200, 'msg': '添加成功'})
else:
return Response({'code': 201, 'msg': ser.errors})
class BookDetailView(APIView):
def get(self, request, pk):
book = Book.objects.filter(pk=pk).first()
ser = BookSerializer(instance=book)
return Response({'code': 200, 'msg': '成功', 'data': ser.data})
def put(self, request, pk):
book = Book.objects.filter(pk=pk).first()
ser = BookSerializer(instance=book, data=request.data)
if ser.is_valid():
ser.save()
return Response({'code': 200, 'msg': '修改成功'})
else:
return Response({'code': 201, 'msg': ser.errors})
def delete(self, request, pk):
Book.objects.filter(pk=pk).delete()
return Response('')
序列化类
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
fields = ['title', 'price', 'publish_detail', 'author_list', 'publish', 'author']
extra_kwargs = {
'title': {'max_length': 8},
'publish': {'write_only': True},
'author': {'write_only': True},
}
publish_detail = serializers.DictField(read_only=True)
author_list = serializers.ListField(read_only=True)
Publish的5个接口
表模型
class Publish(models.Model):
name = models.CharField(max_length=32)
addr = models.CharField(max_length=32)
视图类
class PublishView(APIView):
def get(self, request):
publish = Publish.objects.all()
ser = PublishSerializer(instance=publish, many=True)
return Response({'code': 200, 'msg': '成功', 'data': ser.data})
def post(self, request):
ser = PublishSerializer(data=request.data)
if ser.is_valid():
ser.save()
return Response({'code': 200, 'msg': '添加成功'})
else:
return Response({'code': 201, 'msg': ser.errors})
class PublishDetailView(APIView):
def get(self, request, pk):
publish = Publish.objects.filter(pk=pk).first()
ser = PublishSerializer(instance=publish)
return Response({'code': 200, 'msg': '成功', 'data': ser.data})
def put(self, request, pk):
publish = Publish.objects.filter(pk=pk).first()
ser = PublishSerializer(instance=publish, data=request.data)
if ser.is_valid():
ser.save()
return Response({'code': 200, 'msg': '修改成功'})
else:
return Response({'code': 201, 'msg': ser.errors})
def delete(self, request, pk):
Publish.objects.filter(pk=pk).delete()
return Response('')
序列化类
class PublishSerializer(serializers.ModelSerializer):
class Meta:
model = Publish
fields = '__all__'
Author的5个接口
表模型
class Author(models.Model):
name = models.CharField(max_length=32)
phone = models.IntegerField()
author_detail = models.OneToOneField(to='Author_detail', on_delete=models.CASCADE)
# @property # 此处注释是因为有种写的方法,一是使用source进行关联查询,二是使用此方法进行字段的定制
# def email(self):
# return self.author_detail.email
#
# @property
# def age(self):
# return self.author_detail.age
class Author_detail(models.Model):
email = models.CharField(max_length=32)
age = models.IntegerField()
视图类
class AuthorView(APIView):
def get(self, request):
author = Author.objects.all()
ser = AuthorSerializer(instance=author, many=True)
return Response({'code': 200, 'msg': '成功', 'data': ser.data})
def post(self, request):
ser = AuthorSerializer(data=request.data)
if ser.is_valid():
ser.save()
return Response({'code': 200, 'msg': '添加成功'})
else:
return Response({'code': 201, 'msg': ser.errors})
class AuthorDetailView(APIView):
def get(self, request, pk):
author = Author.objects.filter(pk=pk).first()
ser = AuthorSerializer(instance=author)
return Response({'code': 200, 'msg': '成功', 'data': ser.data})
def put(self, request, pk):
author = Author.objects.filter(pk=pk).first()
ser = AuthorSerializer(instance=author, data=request.data)
if ser.is_valid():
ser.save()
return Response({'code': 200, 'msg': '修改成功'})
else:
return Response({'code': 201, 'msg': ser.errors})
def delete(self, request, pk):
Author.objects.filter(pk=pk).delete()
return Response('')
序列化类
class AuthorSerializer(serializers.ModelSerializer):
class Meta:
model = Author
fields = ['name', 'phone', 'email', 'age']
extra_kwargs = {
'name': {'max_length': 8},
}
email = serializers.CharField(source='author_detail.email')
age = serializers.IntegerField(source='author_detail.age')
def create(self, validated_data):
author_detail_value = validated_data.pop('author_detail')
try:
with transaction.atomic():
author_detail = Author_detail.objects.create(**author_detail_value)
validated_data['author_detail'] = author_detail
author = Author.objects.create(**validated_data)
except Exception as e:
print(e)
transaction.rollback()
# author_detail = Author_detail.objects.create(email=validated_data['email'], age=validated_data['age'])
# author = Author.objects.create(name=validated_data['name'], phone=validated_data['phone'], author_detail=author_detail)
# 虽然可以这么写但是,比较麻烦而且字段多了不好操作
return author
def update(self, author, validated_data):
author_detail = author.author_detail
author_detail_value = validated_data.pop('author_detail')
try:
with transaction.atomic():
for i in validated_data:
setattr(author, i, validated_data[i])
for i in author_detail_value:
setattr(author_detail, i, author_detail_value[i])
except Exception as e:
print(e)
transaction.rollback()
else:
author.save()
author_detail.save()
return author
标签:ModelSerializer,ser,author,detail,publish,用法,序列化,data
From: https://www.cnblogs.com/juzixiong/p/17413095.html