详情组件我们之前写了ArticleDetail组件,目前只能展示article+ID等一串文字。让我们修改代码,让这个组件显示文章的实际内容。.首先我们当前点击首页的文章标题,指向的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的地方。然后修改ArticleDetail.js:importReact,{useEffect,useState}from"react";从'react-router-dom'导入{useParams};constArticleDetail=()=>{//HOOKconst{articleId}=useParams();const[loading,setLoading]=useState(true);const[文章,setArticle]=useState({});constfetchArticle=()=>{fetch(`/api/articles/${articleId}/`).then(response=>response.json()).then(result=>{setArticle(result);setLoading(false);}).catch(e=>console.log(e));}useEffect(fetchArticle,[])返回(loading?
Loading...
:
{article.title}
{article.body}
)}exportdefaultArticleDetail代码糟透了,仅供参考。我们之前讨论过类组件。只有类组件才有生命周期和状态,而现在React有了HOOK的功能。看我们的代码,这里开始使用的是HOOK。useState使函数组件可以像类组件一样使用状态。它使用一个参数作为初始值并返回一个数组。比如代码中第7行的loading部分,我们给名为loading的状态赋初值false,返回的数组第一个元素是loading状态,第二个是一个函数,可以用来改变状态值。然后我们定义一个获取文章的函数,获取结果后设置文章,设置加载状态为false。useEffect类似于类组件的componentDidMount生命周期函数。组件挂载后,会执行传参的回调函数,获取文章数据。第二个参数[]让这个函数只在组件挂载后运行一次。关于HOOK的详细信息,请参考React官方文档。我不会在返回值部分谈论JSX。只是三元运算符根据加载状态进行条件渲染,并没有什么特别之处。刚才动态字段的详情页,主要是说明一个情况。对于后端定义的API,并不是任何地方都需要所有数据。比如首页,我们只需要文章标题和发布时间,详情页展示文章内容。虽然硬件条件越来越好,但是如果所有的数据都通过网络传输到客户端,无疑是一种网络资源的浪费。但是,为不同的前端页面定义不同的序列化器或修改模型太麻烦了。我们可以通过在请求中定义参数如fields=xx,xxx来实现。已经有一个有用的第三方库来帮助我们做到了。那就是drf-flex-fields,让我们使用pip来安装:$pipinstalldrf-flex-fields使用起来也很简单,修改article/serializers.py即可:fromrest_flex_fieldsimportFlexFieldsModelSerializerfromarticle.modelsimportArticlefromrest_frameworkimport序列化程序类ArticleSerializer(FlexFieldsModelSerializer):author=serializers.ReadOnlyField(source='author.username')classMeta:model=Articlefields=['id','author','title','body','created','更新']用命令行测试它:$http://127.0.0.1:8000/api/articles/\?fields\=author,body...[{"author":"elliot","body":"时间测试"},{"author":"elliot","body":"现在是4月5日11:10"}]$http://127.0.0.1:8000/api/articles/\?omit\=author,body...[{"created":"2020-04-05T11:47:49.087547+08:00","id":2,"title":"currenttime","updated":"2020-04-05T11:47:49.087580+08:00"},{"created":"2020-04-05T11:10:56.880622+08:00","id":1,"title":"Firstday","updated":"2020-04-05T11:10:56.880674+08:00"}]可以通过fields参数指定必填字段,也可以通过omit指定需要排除的字段哪些字段注意url中的参数要以问号开头?,和\?应该用于转义命令行中的问号。这时候可以修改前端代码:......constArticleItem=props=>(
......{/*删除这一行//修改这里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...欢迎关注我的公众号《公子政的日常》,第一时间推送原创技术文章。