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
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) |
|
|
|
|
|
|
|
|