1
- 博客文章通常需要分类,方便用户快速识别文章的类型,或者进行过滤操作。
1
+ 博客文章通常需要分类,方便用户快速识别文章的类型,或者进行某种关联操作。
2
+
3
+ 本章就来实现对文章的分类。
2
4
3
5
## 增加分类模型
4
6
@@ -34,11 +36,11 @@ class Article(models.Model):
34
36
35
37
```
36
38
37
- 比较简单的分类模型 ,大体上就 ` title ` 字段会用到。
39
+ 字段很简单 ,大体上就 ` title ` 字段会用到。
38
40
39
41
别忘了数据迁移。
40
42
41
- > 教程为了简单起见就把分类的 model 放到 article 目录中了 。实际项目应根据情况考虑是否需要另起一个单独的分类 app。
43
+ > 教程把分类的 model 放到 article app中了 。实际项目应根据情况考虑是否需要另起一个单独的分类 app。
42
44
43
45
## 视图与路由
44
46
@@ -126,26 +128,26 @@ class ArticleSerializer(serializers.HyperlinkedModelSerializer):
126
128
127
129
先看 ` CategorySerializer ` :
128
130
129
- - ` HyperlinkedIdentityField ` 前面章节有讲过,作用是将路由间的表示转换为超链接。` view_name ` 参数是路由的别名 ,你必须显示指定。 ` category-detail ` 是自动注册路由时,` Router ` 默认帮你设置的详情页面的名称,类似的还有 ` category-list ` 等,更多规则参考[ 文档] ( https://www.django-rest-framework.org/api-guide/routers/#defaultrouter ) 。
131
+ - ` HyperlinkedIdentityField ` 前面章节有讲过,作用是将路由间的表示转换为超链接。` view_name ` 参数是路由名 ,你必须显示指定。 ` category-detail ` 是自动注册路由时,` Router ` 默认帮你设置的详情页面的名称,类似的还有 ` category-list ` 等,更多规则参考[ 文档] ( https://www.django-rest-framework.org/api-guide/routers/#defaultrouter ) 。
130
132
- 创建日期不需要后期修改,所以设置为 ` read_only_fields ` 。
131
133
132
- 然后再来看更麻烦一点的 ` ArticleSerializer ` :
134
+ 再来看 ` ArticleSerializer ` :
133
135
134
- - 由于我们希望文章接口不仅仅只返回分类的 id 而已,所以需要显示指定 ` category ` ,将其变成一个嵌套数据,与之前的 ` author ` 类似。
135
- - DRF 框架原生没有实现** 可写的嵌套数据** (因为其操作逻辑没有统一的标准),那我想** 创建/更新** 文章和分类的外键关系怎么办?一种方法是自己去实现序列化器的 ` create()/update() ` 方法;另一种就是 DRF 框架提供了修改外键的一个快捷方式,即显示指定 ` category_id ` 字段,则此字段会自动链接到 ` category ` 外键,以便你更新外键关系。
136
+ - 由于我们希望文章接口不仅仅只返回分类的 id 而已,所以需要显式指定 ` category ` ,将其变成一个嵌套数据,与之前的 ` author ` 类似。
137
+ - DRF 框架原生没有实现** 可写的嵌套数据** (因为其操作逻辑没有统一的标准),那我想** 创建/更新** 文章和分类的外键关系怎么办?一种方法是自己去实现序列化器的 ` create()/update() ` 方法;另一种就是 DRF 框架提供的修改外键的快捷方式,即显式指定 ` category_id ` 字段,则此字段会自动链接到 ` category ` 外键,以便你更新外键关系。
136
138
- 再看 ` category_id ` 内部。` write_only ` 表示此字段仅需要可写;` allow_null ` 表示允许将其设置为空;` required ` 表示在** 创建/更新** 时可以不设置此字段。
137
139
138
140
经过以上设置,实际上序列化器已经可以正常工作了。但有个小问题是如果用户提交了一个不存在的分类外键,后端会返回外键数据不存在的 500 错误,不太友好。解决方法就是对数据预先进行** 验证** 。
139
141
140
142
验证方式又有如下几种:
141
143
142
- - 覆写序列化器的 ` validate() ` 方法。这是个全局的验证器,其接收的唯一参数是所有字段值的字典。当你需要同时对多个字段进行验证时,这是个很好的选择。
143
- - 另一种就是教程用的方法 ,即 ` validate_{field_name} ` 方法,它会只验证某个特定的字段,比如 ` category_id ` 。
144
+ - 覆写序列化器的 ` . validate(... )` 方法。这是个全局的验证器,其接收的唯一参数是所有字段值的字典。当你需要同时对多个字段进行验证时,这是个很好的选择。
145
+ - 另一种就是教程用到的 ,即 ` . validate_{field_name}(...) ` 方法,它会只验证某个特定的字段,比如 ` category_id ` 。
144
146
145
147
` validate_category_id ` 检查了两样东西:
146
148
147
149
- 数据库中是否包含了对应 id 值的数据。
148
- - 传入值是否为 None。这是为了能够将已有的外键置空而设置的 。
150
+ - 传入值是否为 None。这是为了能够将已有的外键置空 。
149
151
150
152
如果没通过上述检查,后端就抛出一个 400 错误(代替之前的 500 错误),并返回错误产生的提示,这就更友好一些了。
151
153
@@ -155,9 +157,9 @@ class ArticleSerializer(serializers.HyperlinkedModelSerializer):
155
157
156
158
打开命令行,首先创建分类:
157
159
158
- > 你创建的数据 id 和博主的不一定相同,不要惊慌这是正常的,因为我在写文章时会反复进行测试 ,确保正确。再重复一次,如果你更喜欢图形化的界面,请下载 Postman 。
160
+ > 你创建的数据 id 和博主的不一定相同,这是正常的,因为我在写教程时会反复测试 ,确保正确。
159
161
160
- ```
162
+ ``` python
161
163
C:\...> http -a dusai:admin123456 POST http://127.0.0.1:8000/api/category/ title=Django
162
164
...
163
165
@@ -214,7 +216,7 @@ C:\Users\Dusai>http -a dusai:admin123456 PATCH http://127.0.0.1:8000/api/article
214
216
}
215
217
```
216
218
217
- 这里细心一点的就会发现,我们在更新资源时用到了 ` POST ` 、` PUT ` 、 ` PATCH ` 三种请求方法,它们在 DRF 中的区别是啥 ?
219
+ 这里细心一点的就会发现,在更新资源时用到了 ` POST ` 、` PUT ` 、 ` PATCH ` 三种请求方法,它们的区别是啥 ?
218
220
219
221
- ` POST ` :创建新的资源。
220
222
- ` PUT ` : 整体更新特定资源,默认情况下你需要完整给出所有必须的字段。
@@ -279,4 +281,4 @@ class CategoryViewSet(viewsets.ModelViewSet):
279
281
return CategoryDetailSerializer
280
282
```
281
283
282
- 除此之外没有新的魔法,轻松搞定 。
284
+ 除此之外没有新的魔法。
0 commit comments