1
- 一篇文章通常还有多个标签,作为分类功能的补充 。
1
+ 一篇文章通常还有 ** 标签 ** 功能,作为分类的补充 。
2
2
3
3
## 模型和视图
4
4
@@ -31,7 +31,9 @@ class Article(models.Model):
31
31
)
32
32
```
33
33
34
- 一篇文章可以有多个标签,一个标签可以对应多个文章,因此是** 多对多** 关系。写完后记得迁移。
34
+ 一篇文章可以有多个标签,一个标签可以对应多个文章,因此是** 多对多** 关系。
35
+
36
+ > 写完后记得迁移。
35
37
36
38
接着把视图集也写好:
37
39
@@ -62,7 +64,7 @@ router.register(r'tag', views.TagViewSet)
62
64
63
65
## 序列化器
64
66
65
- 接下来就是最重要的` TagSerializer ` :
67
+ 接下来就是最重要的 ` TagSerializer ` :
66
68
67
69
``` python
68
70
# article/serializers.py
@@ -92,7 +94,7 @@ class ArticleSerializer(serializers.HyperlinkedModelSerializer):
92
94
...
93
95
```
94
96
95
- 我们已经知道,默认的嵌套序列化器显示外链的 id,需要改得更友好一些。但似乎又没必要改为超链接 ,因为标签就 ` text ` 字段有用。因此就用 ` SlugRelatedField ` 直接显示其 ` text ` 字段得内容就足够了 。
97
+ 通过前面章节已经知道,默认的嵌套序列化器只显示外链的 id,需要改得更友好一些。但似乎又没必要改为超链接或者字段嵌套 ,因为标签就 ` text ` 字段有用。因此就用 ` SlugRelatedField ` 直接显示其 ` text ` 字段的内容就足够了 。
96
98
97
99
让我们给已有的文章新增一个叫 ` java ` 的标签试试:
98
100
@@ -107,13 +109,13 @@ PS C:\...> http -a dusai:admin123456 PATCH http://127.0.0.1:8000/api/article/26/
107
109
}
108
110
```
109
111
110
- > 这里再强调一下,与发送请求有关的命令行均指 PowerShell。 指令里 tags 那里面带那么多斜杠的写法都是 windows 的老毛病造成的。用 Postman 并不需要。
112
+ > 指令里 tags 里面带那么多斜杠的写法都是 windows 的老毛病造成的。用 Postman 并不需要。
111
113
112
- 修改失败了,原因是 ` java ` 标签不存在。多对多关系,DRF 框架默认你必须先得有这个外键对象 ,才能指定其关系。虽然也合情合理,但我们更希望在创建、更新文章时,程序会** 自动检查** 数据库里是否存在当前标签。如果存在则链接它,如果不存在则创建一个并链接它 。
114
+ 修改失败了,原因是 ` java ` 标签不存在。多对多关系,DRF 默认你必须先得有这个外键对象 ,才能指定其关系。虽然也合情合理,但我们更希望在创建、更新文章时,程序会** 自动检查** 数据库里是否存在当前标签。如果存在则指向它,如果不存在则创建一个并指向它 。
113
115
114
- 要实现这个效果,你可以很快就会想到覆写 ` validate_{field_name}() ` 或者 ` validate() ` 还或者 ` create()/update() ` 方法。但是很遗憾,它们都是不行的。
116
+ 要实现这个效果,你可能想到覆写 ` . validate_{field_name}()` 或者 ` . validate()` 还或者 ` . create()/. update()` 方法。但是很遗憾,它们都是不行的。
115
117
116
- 原因是 DRF 框架执行默认的字段有效性验证比上述的方法都早 ,程序还执行不到上述的方法,框架就已经抛出错误了。
118
+ 原因是 DRF 执行默认的字段有效性检查比上述的方法都早 ,程序还执行不到上述的方法,框架就已经抛出错误了。
117
119
118
120
正确的解法是覆写 ` to_internal_value() ` 方法:
119
121
@@ -136,7 +138,7 @@ class ArticleSerializer(serializers.HyperlinkedModelSerializer):
136
138
return super ().to_internal_value(data)
137
139
```
138
140
139
- ` to_internal_value() ` 方法本身的主要作用是将请求中的原始数据转化为 Python 表示形式(期间还会对字段有效性做初步检查)。它的执行时间比默认验证器的字段检查更早,因此有机会在此方法中将需要的数据创建好,然后等待检查的降临。` isinstance() ` 确定标签数据是列表,才会循环并创建新数据。
141
+ ` to_internal_value() ` 方法原本作用是将请求中的原始 Json 数据转化为 Python 表示形式(期间还会对字段有效性做初步检查)。它的执行时间比默认验证器的字段检查更早,因此有机会在此方法中将需要的数据创建好,然后等待检查的降临。` isinstance() ` 确定标签数据是列表,才会循环并创建新数据。
140
142
141
143
再重新请求试试:
142
144
@@ -249,4 +251,6 @@ class ArticleSerializer(serializers.HyperlinkedModelSerializer):
249
251
fields = ' __all__'
250
252
```
251
253
252
- 标签的增删改查,请读者自行测试吧。
254
+ 标签的增删改查,就请读者自行测试吧。
255
+
256
+ > 无论是通过文章接口还是标签自己的接口,创建新标签应该都是 OK 的。
0 commit comments