Django REST framework - 序列化
目录
Django REST framework 序列化
DRF 序列化的本质
Django ORM对象 --> JSON格式的数据 ==>此过程是序列化
类似json模块中dumps()
JSON格式的数据 --> Django ORM的数据 ==>此过程是反序列化
类似json模块中loads
DRF中序列化工具
from rest_framework.serializers import Serializer
from rest_framework.serializers import MoselSerializer
类比Django中的form组件
Django form --> HTML表单
HTML表单 -->ORM数据
安装DRF
pip install djangorestframework
添加rest_framework应用
注册app(非必须的)
INSTALLED_APPS = [
...
'rest_framework',
]
定义Serializer
class BookInfoSerializer(serializers.Serializer):
pass
or
class BookInfoSerializer(serializers.MoselSerializer):
pass
使用DRF序列化器 示例
表结构
class Article(models.Model):
id = models.AutoField(primary_key=True)
title = models.CharField(max_length=64)
create_time = models.DateField(auto_now=True)
type = models.SmallIntegerField(
choices=((1, '原创'), (2, '转载')),
default=1
)
source = models.ForeignKey(to='Source', on_delete=models.CASCADE)
tag = models.ManyToManyField(to='Tag')
class Source(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=32, unique=True, error_messages={"unique": '校区名称不能重复'})
class Tag(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=32)
class Comment(models.Model):
content = models.CharField(max_length=255)
article = models.ForeignKey(to='Article', on_delete=models.CASCADE)
一. 单表的GET和POST
路由
url(r'source/', views.SourceView.as_view()),
序列化类
class SourceSerializer(serializers.ModelSerializer):
def validate_name(self, value):
if '草' in value:
raise ValidationError('不符合社会主义核心价值观')
return value
class Meta:
model = models.Source
fields = "__all__"
视图
class SourceView(APIView):
def get(self, request, *args, **kwargs):
res = {"code": 0}
all_source = models.Source.objects.all()
ser_obj = SourceSerializer(all_source, many=True)
res["data"] = ser_obj.data
return Response(res)
def post(self, request, *args, **kwargs):
res = {"code": 0}
ser_obj = SourceSerializer(data=request.data)
if ser_obj.is_valid():
# 数据没问题
ser_obj.save()
return Response(res)
else:
res["code"] = 1
res["error"] = ser_obj.errors
return Response(res)
二. 外键的GET和POST
路由
url(r'comment/', views.Comment.as_view()),
序列化
class CommentSerializer(serializers.ModelSerializer):
class Meta:
model = models.Comment
fields = "__all__"
extra_kwargs = {
"content": {"error_messages": {"required": "评论内容不能为空"}},
"article": {"error_messages": {"required": "文章不能为空"}}
}
视图
class Comment(APIView):
def get(self, request, *args, **kwargs):
res = {"code": 0}
all_data = models.Comment.objects.all()
ser_obj = CommentSerializer(all_data, many=True)
res["data"] = ser_obj.data
return Response(res)
def post(self, request, *args, **kwargs):
res = {"code": 0}
ser_obj = CommentSerializer(data=request.data)
if ser_obj.is_valid():
ser_obj.save()
else:
res["code"] = 1
res["error"] = ser_obj.errors
return Response(res)
多对多的GET和POST
路由
url(r'article/', views.ArticleList.as_view()),
序列化
class TagSerializer(serializers.ModelSerializer):
class Meta:
model = models.Tag
fields = "__all__"
class ArticleSerializer(serializers.ModelSerializer):
type = serializers.CharField(source="get_type_display")
tag = TagSerializer(many=True)
class Meta:
model = models.Article
fields = ["id", "title", "type", "source", "tag"]
class ArticleWriteSerializer(serializers.ModelSerializer):
class Meta:
model = models.Article
fields = "__all__"
extra_kwargs = {
"tag": {
"error_messages": {
"does_not_exist": '"{pk_value}"对应的tag对象不存在。'
}
}
}
三. 视图
class ArticleList(APIView):
def get(self, request, *args, **kwargs):
res = {"code": 0}
article_list = models.Article.objects.all()
ser_obj = ArticleSerializer(article_list, many=True)
res["data"] = ser_obj.data
return Response(res)
def post(self, request, *args, **kwargs):
res = {"code": 0}
ser_obj = ArticleWriteSerializer(data=request.data)
if ser_obj.is_valid():
ser_obj.save()
else:
res["code"] = 1
res["error"] = ser_obj.errors
return Response(res)
四. 超链接的序列化
路由
urlpatterns = [
url(r'articlelinked/', views.ArticleLinked.as_view()),,
url(r'source/(?P<pk>\d+)', views.SourceDetailView.as_view(), name='source-detail'),
]
序列化
class ArticleHyperlinkedSerializer(serializers.HyperlinkedModelSerializer):
source = serializers.HyperlinkedIdentityField(view_name='source-detail', lookup_field='source_id', lookup_url_kwarg='pk')
class Meta:
model = models.Article
fields = ["id", "type", "title", "source"]
depth = 1
视图
class ArticleLinked(APIView):
def get(self, request, *args, **kwargs):
res = {"code": 0}
article_list = models.Article.objects.all()
ser_obj = ArticleHyperlinkedSerializer(article_list, many=True, context={'request': request})
res["data"] = ser_obj.data
return Response(res)
序列化补充 跨表的序列化##
方法一
class ModelCourseCategoryView(serializers.ModelSerializer):
# price = serializers.SerializerMethodField()
# learn_num = serializers.SerializerMethodField()
# def get_price(self, obj):
# price_obj = obj.price_policy.all().filter(valid_period=723).first()
# return price_obj.price
#
# def get_learn_num(self, obj):
# return obj.order_details.count()
方法二
source 支持被序列化对象的点操作
learn_num = serializers.IntegerField(source='order_details.count')
course_detail_id = serializers.IntegerField(source='coursedetail.id')
方法三###
to_representation终级方法
# 修改序列化结果的终极方法
def to_representation(self, instance):
# 调用父类的同名方法把序列化的结果拿到
data = super().to_representation(instance)
# 针对序列化的结果做一些自定制操作
# 判断当前这个课程是否有永久有效的价格
price_obj = instance.price_policy.all().filter(valid_period=999).first()
if price_obj:
# 有永久有效的价格
data['has_price'] = True
data['price'] = price_obj.price
else:
# 没有永久有效的价格策略
data['has_price'] = False
return data