You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

176 lines
5.5 KiB

from rest_framework import serializers
from article.models import Article, Category, Tag, Avatar
from user_info.serializers import UserDescSerializer
from comment.serializers import CommentSerializer
class CategorySerializer(serializers.ModelSerializer):
"""所有分类的序列化器"""
# 将路由间的表示转换为超链接
# category-detail是自动注册路由时, Router默认帮你设置的详情页面的名称
url = serializers.HyperlinkedIdentityField(view_name='category-detail')
class Meta:
model = Category
fields = '__all__'
# 创建时间不能修改
read_only_fields = ['created']
class AvatarSerializer(serializers.ModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='avatar-detail')
class Meta:
model = Avatar
fields = '__all__'
class ArticleBaseSerializer(serializers.HyperlinkedModelSerializer):
"""将原来的ArticleSerializer抽象出一个父类"""
# 添加文章id
id = serializers.IntegerField(read_only=True)
author = UserDescSerializer(read_only=True)
# 希望文章接口不仅仅只返回分类的id而已,所以需要显式指定category,将其变成一个嵌套数据,
# 分类的嵌套序列化字段
category = CategorySerializer(read_only=True)
# 显示指定category的id字段,用于创建/更新category外键
category_id = serializers.IntegerField(write_only=True, allow_null=True, required=False)
# 新增tag字段, 直接显示Tag的text字段
tags = serializers.SlugRelatedField(
queryset=Tag.objects.all(),
many=True,
required=False,
slug_field='text',
)
# 图片字段
avatar = AvatarSerializer(read_only=True)
avatar_id = serializers.IntegerField(
write_only=True,
allow_null=True,
required=False,
)
# 自定义错误信息
default_error_messages = {
'incorrect_avatar_id': 'Avatar with id {value} not exists.',
'incorrect_category_id': 'Category with id {value} not exists.',
'default': 'No more message here..'
}
def check_obj_exists_or_fail(self, model, value, message='default'):
if not self.default_error_messages.get(message, None):
message = 'default'
# 不为None但是不存在该id返回错误信息
if not model.objects.filter(id=value).exists() and value is not None:
# 若不存在则调用钩子方法fail()引发错误
self.fail(message, value=value)
# 验证图片id是否正确
def validate_avatar_id(self, value):
self.check_obj_exists_or_fail(
model=Avatar,
value=value,
message='incorrect_avatar_id'
)
return value
# 验证category_id是否正确
def validate_category_id(self, value):
self.check_obj_exists_or_fail(
model=Category,
value=value,
message='incorrect_category_id'
)
return value
def to_internal_value(self, data):
tags_data = data.get('tags')
if isinstance(tags_data, list):
for text in tags_data:
# 不存在该标签则创建它
if not Tag.objects.filter(text=text).exists():
Tag.objects.create(text=text)
return super().to_internal_value(data)
class ArticleSerializer(ArticleBaseSerializer):
"""文章序列化器"""
class Meta:
model = Article
fields = '__all__'
# body字段只可写不可见
extra_kwargs = {'body': {'write_only': True}}
class ArticleDetailSerializer(ArticleBaseSerializer):
id = serializers.IntegerField(read_only=True)
comments = CommentSerializer(many=True, read_only=True)
# 渲染后的正文
body_html = serializers.SerializerMethodField()
# 渲染后的目录
toc_html = serializers.SerializerMethodField()
def get_body_html(self, obj):
return obj.get_md()[0]
def get_toc_html(self, obj):
return obj.get_md()[1]
class Meta:
model = Article
fields = '__all__'
class ArticleCategoryDetailSerializer(serializers.ModelSerializer):
"""分类详情的嵌套序列化器"""
url = serializers.HyperlinkedIdentityField(view_name='article-detail')
class Meta:
model = Article
fields = [
'url',
'title',
]
class CategoryDetailSerializer(serializers.ModelSerializer):
"""具体的分类详情页不显示url"""
# 显示某个分类下的所有文章
articles = ArticleCategoryDetailSerializer(many=True, read_only=True)
class Meta:
model = Category
fields = [
'id',
'title',
'created',
'articles',
]
class TagSerializer(serializers.ModelSerializer):
"""所有标签序列化器"""
# 显示url
# url = serializers.HyperlinkedIdentityField(view_name='tag-detail')
class Meta:
model = Tag
fields = '__all__'
# 创建或者更新前检查是否存在该tag
def check_tag_obj_exists(self, validated_data):
text = validated_data.get('text')
if Tag.objects.filter(text=text).exists():
raise serializers.ValidationError('Tag with text {} exists.'.format(text))
def create(self, validated_data):
self.check_tag_obj_exists(validated_data)
return super().create(validated_data)
def update(self, instance, validated_data):
self.check_tag_obj_exists(validated_data)
return super().update(instance, validated_data)