以前咱们编写了ArticleDetail
这个组件,不过它目前只能显示article+ID
这样一串文本,让咱们修改代码,让这个组件显示实际的文章内容吧。javascript
首先目前咱们点击首页的文章标题,指向的url为articles/id/
,这与咱们后端的url重复了。为此,更改一下backend/urls.py
:前端
urlpatterns = [ path('admin/', admin.site.urls), # 全都放到api这个路径后面 path('api/', include('article.urls')), path('auth/', include('rest_framework_social_oauth2.urls')), ]
注意以前ArticleList
组件中请求API的地方要作出修改哦。java
接着修改ArticleDetail.js
:python
import React, {useEffect, useState} from "react"; import { useParams } from 'react-router-dom'; const ArticleDetail = () => { // HOOK const { articleId } = useParams(); const [loading, setLoading] = useState(true); const [article, setArticle] = useState({}); const fetchArticle = () => { fetch(`/api/articles/${articleId}/`) .then(response => response.json()) .then(result => { setArticle(result); setLoading(false); }) .catch(e => console.log(e)); } useEffect(fetchArticle, []) return ( loading ? <div>加载中...</div> : <div> <h4>{article.title}</h4> <p>{article.body}</p> </div> ) } export default ArticleDetail
代码很烂,仅供参考。以前咱们讲过类组件,只有类组件有生命周期,有state
,可是如今React
有了HOOK
这一功能,看咱们的代码中,以use
开头的地方,都是HOOK
。react
useState
使函数组件能够像类组件同样使用state
,它使用一个参数做为初始值,并返回一个数组,例如代码中第7行loading
部分,咱们给了名为loading
的state
初始值false
,返回的数组中第一个元素是loading
这个state
,而第二个则是一个函数,能够用于更改state
值。git
以后咱们定义一个获取文章的函数,获取结果后设置article
,并将loading
状态设为false
。useEffect
则相似类组件的componentDidMount
这个生命周期函数,在组件挂载后,将会执行经过参数传递的回调函数,获取文章数据。第二个参数[]
使得这个函数只在组件挂载后运行一次。github
有关HOOK
的详情能够去看React
官方文档。json
返回值部分的JSX
就不说了,只是三元运算符根据loading
状态作条件渲染,没有特别的地方。后端
刚刚这个详情页面,其实主要是为了说明一种状况,对于后端定义的API,并非在任何地方都须要所有数据的。例如,在首页咱们只须要文章标题、发布时间,详情页才显示文章内容。尽管如今硬件条件愈来愈好,但若是把全部数据都经过网络传输到客户端,无疑是对网络资源的浪费。api
不过若是为前端不一样页面定义不一样的序列化器或者修改模型那就太麻烦了,咱们能够经过定义请求中的参数如fields=xx,xxx
来实现这一点,已经有一个好用的第三方库帮咱们作到啦。那就是drf-flex-fields,让咱们使用pip来安装:
$ pip install drf-flex-fields
要使用也很是简单,只须要修改article/serializers.py
:
from rest_flex_fields import FlexFieldsModelSerializer from article.models import Article from rest_framework import serializers class ArticleSerializer(FlexFieldsModelSerializer): author = serializers.ReadOnlyField(source='author.username') class Meta: model = Article fields = ['id', 'author', 'title', 'body', 'created', 'updated']
用命令行测试一下:
$ http http://127.0.0.1:8000/api/articles/\?fields\=author,body ... [ { "author": "elliot", "body": "时间测试" }, { "author": "elliot", "body": "如今是4月5日11点10分" } ] $ http http://127.0.0.1:8000/api/articles/\?omit\=author,body ... [ { "created": "2020-04-05T11:47:49.087547+08:00", "id": 2, "title": "如今时间", "updated": "2020-04-05T11:47:49.087580+08:00" }, { "created": "2020-04-05T11:10:56.880622+08:00", "id": 1, "title": "第一天", "updated": "2020-04-05T11:10:56.880674+08:00" } ]
既能够经过fields
参数来指定须要的字段,也能够经过omit
来指定要排除哪些字段。注意url中参数要用问号?
开头,在命令行中则要用\?
来转义问号。
这时候能够去修改前端代码:
...... const ArticleItem = props => ( <div key={props.item.id}> ...... <p> {/* 删掉这行<strong>{props.item.body}</strong>*/} ...... </p> </div> ) class ArticleList extends Component { ...... componentDidMount() { // 修改这里 fetch('/api/articles/?omit=author,body') .then(response => response.json()) .then(result => this.setState({articleList: result})) .catch(e => this.setState({error: e})); } ...... } ......
如今首页就没有文章详细内容了。文章详情组件就留给读者本身去修改了。
drf-flex-fields
这个库的功能可不止于此哦,建议读者去Github看看这个库的说明与源码,可使咱们的API便捷的实现关系型字段的联合查询。
最近对这个系列的文章有些思考,在这里不打算一步一步作一个实际的,或者说好看的,优雅的博客系统,而是想到一些功能,尽可能加上去,实践Django与React的结合,若是有读者但愿我实现什么功能,能够在公众号留言,最终咱们可能会作出一个很奇葩的应用,哈哈。若是想要直接复制代码作一个我的博客,能够参考个人我的博客,Github地址:https://github.com/Eliot00/el...
欢迎关注个人公众号“公子政的宅平常”,原创技术文章第一时间推送。