作者:HelloGitHub-追梦人物[1]
文中所涉及的示例代码,已同步更新到 HelloGitHub-Team 仓库[2]
在 Django博客教程(第二版)[1] 中,我们给博客内容增加了 Markdown 的支持,博客详情接口应该返回解析后的 HTML 内容。
来回顾一下 Post
模型的代码,Markdown 解析后的 HTML 保存在这几个属性中:
class Post(models.Model):
# ...
@property
def toc(self):
return self.rich_content.get("toc", "")
@property
def body_html(self):
return self.rich_content.get("content", "")
@cached_property
def rich_content(self):
return generate_rich_content(self.body)
rich_content
是 body
Markdown 内容解析后的 HTML 内容,使用了 cached_property
装饰器缓存解析后的结果,以降低多次访问的开销。body_html
属性为解析后的正文内容,toc
属性是从正文标题中提取的目录。
toc
和 body_html
这两个属性的值是我们需要序列化并在接口中返回的,那么可否像之前那样,直接在序列化器 PostRetrieveSerializer
的 Meta.fields
中添加这两个属性就行了呢?
答案是不能。之前说过,模型字段不同类型的值都需要不同的序列化字段对其进行序列化,我们之所以能直接在 Meta.fields
中指定需要序列化的字段而不需要额外的代码是因为这些字段都是直接定义在 django 的模型中的。django-rest-framework 可以根据模型中的字段的定义自动推断该使用何种类型的序列化字段,但对于这里提到的 toc
、body_html
属性,django-rest-framework 就无法推断其值的类型,也就无法自动使用对应的序列化字段对其进行序列化了。不过解决方法很简单,既然 django-rest-framework 无法自动推断,那我们就人工指定该使用何种类型的序列化字段就行了。
这里需要序列化的字段值都是字符串,因此在序列化器中显示地指定需要序列化的字段以及使用的系列化字段类型就可以了:
class PostRetrieveSerializer(serializers.ModelSerializer):
category = CategorySerializer()
author = UserSerializer()
tags = TagSerializer(many=True)
toc = serializers.CharField()
body_html = serializers.CharField()
class Meta:
model = Post
fields = [
"id",
"title",
"body",
"created_time",
"modified_time",
"excerpt",
"views",
"category",
"author",
"tags",
"toc",
"body_html",
]
添加完成后,访问一篇文章的详情接口,就可以看到被序列化并返回的文章目录和正文 HTML 内容了。
[1]
HelloGitHub-追梦人物: https://www.zmrenwu.com
[2]
HelloGitHub-Team 仓库:https://github.com/HelloGitHub-Team/HelloDjango-REST-framework-tutorial
关注公众号加入交流群
『讲解开源项目系列』——让对开源项目感兴趣的人不再畏惧、让开源项目的发起者不再孤单。跟着我们的文章,你会发现编程的乐趣、使用和发现参与开源项目如此简单。欢迎联系我(微信:xueweihan,备注:讲解)加入我们,让更多人爱上开源、贡献开源~
往期回顾:
第 7 篇:文章详情的 API 接口
第 6 篇:分页接口
第 5 篇:用视图集,简化你的代码
“阅读原文”获取更多信息、“在看”让本文被更多人看到、“赞赏”支持我们。