以前咱們編寫了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...
歡迎關注個人公衆號「公子政的宅平常」,原創技術文章第一時間推送。