Serializer
Posted tangshuo
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Serializer相关的知识,希望对你有一定的参考价值。
API
serializers.Serializer
序列化
read_only = True
choice字段
category = serializers.ChoiceField(
choices=CHOICES, source=‘get_category_display‘)
一对多 & 多对多
先把其他序列化类(publisherserializer,authorserializer)写完
通过有没有many = True来区分 一对多和多对多
publisher = PublisherSerializer() # 一对多
author = AuthorSerializer(many=True) # 多对多
def get(self, request):
# book_obj = Book.objects.first()
# serializer = BookSerilizer(book_obj) ## 通过data区分是get 还是post
book_list = Book.objects.all()
serializer = BookSerilizer(book_list, many=True) ## 通过data区分是get 还是post
return Response(serializer.data)
反序列化
write_only = True
注意事项
-
看源码
-
分析前端传什么字段,区分不同的字段
-
def post(self, request): book_obj = request.data serializer = BookSerilizer(data=book_obj) ## 通过data区分 是get还是post请求 if serializer.is_valid(): serializer.save() return Response(serializer.data) return Response(serializer.errors)
-
serializer 要重写 cerate方法 ==》 看源码 返回值
def create(self, validated_data): book_obj = Book.objects.create( title=validated_data[‘title‘], category=validated_data[‘s_category‘], pub_time=validated_data[‘pub_time‘], publisher_id=validated_data[‘s_publisher‘]) book_obj.author.add(*validated_data[‘s_author‘]) return book_obj
serializers.ModelSerializer
一对多 多对多 choice字段
extra_kwargs
def get_s_category(self,obj):
return obj.get_category_display() # choice
def get_s_author(self, obj): # 多对对
author_queryset = Author.objects.all()
return [{"title": item.name} for item in author_queryset]
def get_s_publisher(self, obj): # 一对多
return obj.publisher.title
校验
validate_字段(self,value)
# def validate_title(self, value):
# if "python" not in value.lower():
# raise serializers.ValidationError("标题必须含有python")
# return value
valudate(self,attrs)
# def validate(self, attrs):
# if attrs["w_category"] == 1 and attrs["publisher_id"] == 1:
# return attrs
# else:
# raise serializers.ValidationError("分类以及标题不符合要求")
自定义函数校验
def my_validate(value):
if "敏感信息" in value.lower():
raise serializers.ValidationError("不能含有敏感信息")
else:
return value
回顾
APIView ( 可以 )
from rest_framework.response import Response
class UserModelSerializer(serializers.ModelSerializer):
class Meta:
model = models.UserInfo
fields = "__all__"
class UserView(APIView):
def get(self,request,*args,**kwargs):
user_list = models.UserInfo.objects.all()
ser = UserModelSerializer(instance=user_list,many=True)
return Response(ser.data)
def post(self,request,*args,**kwargs):
ser = UserModelSerializer(data=request.data)
if ser.is_valid():
# models.UserInfo.objects.create(**ser.validated_data)
ser.save(user_id=1)
return Response(ser.data)
return Response(ser.errors)
ListAPIView
ListAPIView,CreateAPIView,RetrieveAPIView,UpdateAPIView,DestroyAPIView
class NewTestModelSerializer(serializers.ModelSerializer):
class Meta:
model = models.News
fields = "__all__"
class NewTestView(CreateAPIView,ListAPIView):
serializer_class = NewTestModelSerializer
queryset = models.News.objects.filter(id__gt=4)
用户传一些值
创建用户时,自己在后台生成一个UID。
class NewTestModelSerializer(serializers.ModelSerializer):
class Meta:
model = models.News
fields = "__all__"
class NewTestView(CreateAPIView,ListAPIView):
serializer_class = NewTestModelSerializer
queryset = models.News.objects.filter(id__gt=4)
def perform_create(self, serializer):
serializer.save(uid=str(uuid.uuid4()))
fields和exclude的区别?
通过fields和exclude定制页面展示数据。
需求:只显示用户表的id,name,age的数据,其他不显示。
class NewTestModelSerializer(serializers.ModelSerializer):
class Meta:
model = models.News
# fields = ["id","name",‘age‘]
# fields = "__all__"
exclude = [‘gender‘]
class NewTestView(ListAPIView):
serializer_class = NewTestModelSerializer
queryset = models.User.objects.all()
[
{id:1,name:‘xxx‘,age:18},
{id:1,name:‘xxx‘,age:11},
{id:1,name:‘xxx‘,age:99},
]
需求:数据库有5个字段,显示7个字段。
class NewTestModelSerializer(serializers.ModelSerializer):
xx = serializers.CharField(source=‘id‘)
x1 = serializers.SerializerMethodField()
class Meta:
model = models.News
# fields = "__all__"
# fields = [‘id‘,‘name‘,‘age‘,‘gender‘,‘phone‘,‘xx‘,‘x1‘]
exclude = [‘id‘,‘name‘]
def get_x1(self,obj):
return obj.id
class NewTestView(ListAPIView):
serializer_class = NewTestModelSerializer
queryset = models.User.objects.all()
[
{id:1,name:‘xxx‘,age:18... xx:1,x1:1},
{id:2,name:‘xxx‘,age:11... xx:2,x1:2},
{id:3,name:‘xxx‘,age:99, xx:3,x1:3},
]
read_only
添加时不要,查看时候需要。
需求:编写两个接口 添加(3字段)、获取列表(5个字段)
class NewTestModelSerializer(serializers.ModelSerializer):
# phone = serializers.CharField(source=‘phone‘,read_only=True)
# email = serializers.CharField(source=‘email‘,read_only=True)
class Meta:
model = models.News
fields = "__all__"
read_only_fields = [‘phone‘,‘email‘,]
class NewTestView(CreateAPIView, ListAPIView):
serializer_class = NewTestModelSerializer
queryset = models.User.objects.all()
添加:
{
name:‘xx‘,
age:‘19‘,
gender:1
}
获取:
[
{name:‘xx‘,age:‘xx‘,gender:‘‘,phone:‘xx‘,email:xxx}
]
复杂需求
添加时用一个serializers、列表时用一个serializers
class NewTestModelSerializer1(serializers.ModelSerializer):
class Meta:
model = models.News
fields = "__all__"
class NewTestModelSerializer2(serializers.ModelSerializer):
class Meta:
model = models.News
fields = "__all__"
class NewTestView(CreateAPIView, ListAPIView):
queryset = models.User.objects.all()
def get_serializer_class(self):
if self.request.method == ‘POST‘:
return NewTestModelSerializer1
if self.request.method == ‘GET‘:
return NewTestModelSerializer2
serializers嵌套
class CreateNewsTopicModelSerializer(serializers.Serializer):
key = serializers.CharField()
cos_path = serializers.CharField()
class CreateNewsModelSerializer(serializers.ModelSerializer):
imageList = CreateNewsTopicModelSerializer(many=True)
class Meta:
model = models.News
exclude = [‘user‘, ‘viewer_count‘, ‘comment_count‘,"favor_count"]
def create(self, validated_data):
# 把imageList切走
image_list = validated_data.pop(‘imageList‘)
# 创建New表中的数据
news_object = models.News.objects.create(**validated_data)
data_list = models.NewsDetail.objects.bulk_create(
[models.NewsDetail(**info, news=news_object) for info in image_list]
)
news_object.imageList = data_list
if news_object.topic:
news_object.topic.count += 1
news_object.save()
return news_object
class NewsView(CreateAPIView):
"""
发布动态
"""
serializer_class = CreateNewsModelSerializer
def perform_create(self, serializer):
# 只能保存:News表中的数据()
# 调用serializer对象的save(先调用create)
new_object = serializer.save(user_id=1)
return new_object
Other
手机号校验
from rest_framework import serializers
from rest_framework.exceptions import ValidationError
import re
def phone_validator(value):
if not re.match(r"^(1[3|4|5|6|7|8|9])d{9}$", value):
raise ValidationError(‘手机格式错误‘)
class MessageSerializer(serializers.Serializer):
phone = serializers.CharField(label=‘手机号‘, validators=[phone_validator, ])
serializer互相嵌套
API
serializers.Serializer
序列化
read_only = True
choice字段
category = serializers.ChoiceField(
choices=CHOICES, source=‘get_category_display‘)
一对多 & 多对多
先把其他序列化类(publisherserializer,authorserializer)写完
通过有没有many = True来区分 一对多和多对多
publisher = PublisherSerializer() # 一对多
author = AuthorSerializer(many=True) # 多对多
def get(self, request):
# book_obj = Book.objects.first()
# serializer = BookSerilizer(book_obj) ## 通过data区分是get 还是post
book_list = Book.objects.all()
serializer = BookSerilizer(book_list, many=True) ## 通过data区分是get 还是post
return Response(serializer.data)
反序列化
write_only = True
注意事项
-
看源码
-
分析前端传什么字段,区分不同的字段
-
def post(self, request): book_obj = request.data serializer = BookSerilizer(data=book_obj) ## 通过data区分 是get还是post请求 if serializer.is_valid(): serializer.save() return Response(serializer.data) return Response(serializer.errors)
-
serializer 要重写 cerate方法 ==》 看源码 返回值
def create(self, validated_data): book_obj = Book.objects.create( title=validated_data[‘title‘], category=validated_data[‘s_category‘], pub_time=validated_data[‘pub_time‘], publisher_id=validated_data[‘s_publisher‘]) book_obj.author.add(*validated_data[‘s_author‘]) return book_obj
serializers.ModelSerializer
一对多 多对多 choice字段
extra_kwargs
def get_s_category(self,obj):
return obj.get_category_display() # choice
def get_s_author(self, obj): # 多对对
author_queryset = Author.objects.all()
return [{"title": item.name} for item in author_queryset]
def get_s_publisher(self, obj): # 一对多
return obj.publisher.title
校验
validate_字段(self,value)
# def validate_title(self, value):
# if "python" not in value.lower():
# raise serializers.ValidationError("标题必须含有python")
# return value
valudate(self,attrs)
# def validate(self, attrs):
# if attrs["w_category"] == 1 and attrs["publisher_id"] == 1:
# return attrs
# else:
# raise serializers.ValidationError("分类以及标题不符合要求")
自定义函数校验
def my_validate(value):
if "敏感信息" in value.lower():
raise serializers.ValidationError("不能含有敏感信息")
else:
return value
回顾
APIView ( 可以 )
from rest_framework.response import Response
class UserModelSerializer(serializers.ModelSerializer):
class Meta:
model = models.UserInfo
fields = "__all__"
class UserView(APIView):
def get(self,request,*args,**kwargs):
user_list = models.UserInfo.objects.all()
ser = UserModelSerializer(instance=user_list,many=True)
return Response(ser.data)
def post(self,request,*args,**kwargs):
ser = UserModelSerializer(data=request.data)
if ser.is_valid():
# models.UserInfo.objects.create(**ser.validated_data)
ser.save(user_id=1)
return Response(ser.data)
return Response(ser.errors)
ListAPIView
ListAPIView,CreateAPIView,RetrieveAPIView,UpdateAPIView,DestroyAPIView
class NewTestModelSerializer(serializers.ModelSerializer):
class Meta:
model = models.News
fields = "__all__"
class NewTestView(CreateAPIView,ListAPIView):
serializer_class = NewTestModelSerializer
queryset = models.News.objects.filter(id__gt=4)
用户传一些值
创建用户时,自己在后台生成一个UID。
class NewTestModelSerializer(serializers.ModelSerializer):
class Meta:
model = models.News
fields = "__all__"
class NewTestView(CreateAPIView,ListAPIView):
serializer_class = NewTestModelSerializer
queryset = models.News.objects.filter(id__gt=4)
def perform_create(self, serializer):
serializer.save(uid=str(uuid.uuid4()))
fields和exclude的区别?
通过fields和exclude定制页面展示数据。
需求:只显示用户表的id,name,age的数据,其他不显示。
class NewTestModelSerializer(serializers.ModelSerializer):
class Meta:
model = models.News
# fields = ["id","name",‘age‘]
# fields = "__all__"
exclude = [‘gender‘]
class NewTestView(ListAPIView):
serializer_class = NewTestModelSerializer
queryset = models.User.objects.all()
[
{id:1,name:‘xxx‘,age:18},
{id:1,name:‘xxx‘,age:11},
{id:1,name:‘xxx‘,age:99},
]
需求:数据库有5个字段,显示7个字段。
class NewTestModelSerializer(serializers.ModelSerializer):
xx = serializers.CharField(source=‘id‘)
x1 = serializers.SerializerMethodField()
class Meta:
model = models.News
# fields = "__all__"
# fields = [‘id‘,‘name‘,‘age‘,‘gender‘,‘phone‘,‘xx‘,‘x1‘]
exclude = [‘id‘,‘name‘]
def get_x1(self,obj):
return obj.id
class NewTestView(ListAPIView):
serializer_class = NewTestModelSerializer
queryset = models.User.objects.all()
[
{id:1,name:‘xxx‘,age:18... xx:1,x1:1},
{id:2,name:‘xxx‘,age:11... xx:2,x1:2},
{id:3,name:‘xxx‘,age:99, xx:3,x1:3},
]
read_only
添加时不要,查看时候需要。
需求:编写两个接口 添加(3字段)、获取列表(5个字段)
class NewTestModelSerializer(serializers.ModelSerializer):
# phone = serializers.CharField(source=‘phone‘,read_only=True)
# email = serializers.CharField(source=‘email‘,read_only=True)
class Meta:
model = models.News
fields = "__all__"
read_only_fields = [‘phone‘,‘email‘,]
class NewTestView(CreateAPIView, ListAPIView):
serializer_class = NewTestModelSerializer
queryset = models.User.objects.all()
添加:
{
name:‘xx‘,
age:‘19‘,
gender:1
}
获取:
[
{name:‘xx‘,age:‘xx‘,gender:‘‘,phone:‘xx‘,email:xxx}
]
复杂需求
添加时用一个serializers、列表时用一个serializers
class NewTestModelSerializer1(serializers.ModelSerializer):
class Meta:
model = models.News
fields = "__all__"
class NewTestModelSerializer2(serializers.ModelSerializer):
class Meta:
model = models.News
fields = "__all__"
class NewTestView(CreateAPIView, ListAPIView):
queryset = models.User.objects.all()
def get_serializer_class(self):
if self.request.method == ‘POST‘:
return NewTestModelSerializer1
if self.request.method == ‘GET‘:
return NewTestModelSerializer2
serializers嵌套
class CreateNewsTopicModelSerializer(serializers.Serializer):
key = serializers.CharField()
cos_path = serializers.CharField()
class CreateNewsModelSerializer(serializers.ModelSerializer):
imageList = CreateNewsTopicModelSerializer(many=True)
class Meta:
model = models.News
exclude = [‘user‘, ‘viewer_count‘, ‘comment_count‘,"favor_count"]
def create(self, validated_data):
# 把imageList切走
image_list = validated_data.pop(‘imageList‘)
# 创建New表中的数据
news_object = models.News.objects.create(**validated_data)
data_list = models.NewsDetail.objects.bulk_create(
[models.NewsDetail(**info, news=news_object) for info in image_list]
)
news_object.imageList = data_list
if news_object.topic:
news_object.topic.count += 1
news_object.save()
return news_object
class NewsView(CreateAPIView):
"""
发布动态
"""
serializer_class = CreateNewsModelSerializer
def perform_create(self, serializer):
# 只能保存:News表中的数据()
# 调用serializer对象的save(先调用create)
new_object = serializer.save(user_id=1)
return new_object
Other
手机号校验
from rest_framework import serializers
from rest_framework.exceptions import ValidationError
import re
def phone_validator(value):
if not re.match(r"^(1[3|4|5|6|7|8|9])d{9}$", value):
raise ValidationError(‘手机格式错误‘)
class MessageSerializer(serializers.Serializer):
phone = serializers.CharField(label=‘手机号‘, validators=[phone_validator, ])
serializer互相嵌套
images = NewsDetailModelSerializer(Many=True) ==> images字段 [ {},{} ... ]
images = NewsDetailModelSerializer(Many=True) ==> images字段 [ {},{} ... ]
以上是关于Serializer的主要内容,如果未能解决你的问题,请参考以下文章
DRF框架serializer之ModelSerializer