寫作一本技術書,能給一個社群帶來哪些改變?
寫作《Flask Web開發實戰》花費了一年多的時間,在這期間,除了編寫5個專案例項和寫作外,我還花了一部分時間來和書中涉及的Python庫(主要是Flask擴充套件)打交道。這篇文章總結了這本書的寫作給整個Flask社群帶來的一些改變。
國內第一本Flask書
雖然國內已經有幾本書介紹過Flask,但都是順便介紹,而不是真正意義上的Flask書。因此,這本書可以說是國內第一本Flask書,很高興能為國內的Flask社群帶來這樣一本書。希望這本書能夠推動更多人瞭解和使用Flask,進而為社群貢獻更多的力量。
完善多個專案
在實際介紹和使用某個庫時,總會遇到各種各樣的問題,主要有兩類:
- Bug
- 不完善的用法或實現
Bug不用多說,肯定要處理。對於不完善的用法和實現,如果沿用原來的程式碼,一來不容易讀者理解,二來還需要在書中加進很多不必要的內容。所以,我更傾向於讓這些程式碼變得更好一點。
如果把不完善的實現寫到書裡,我會覺得非常不舒服。比如說,WTForms本身是支援設定內建的錯誤訊息的語言的,我們可以設為中文,而不用手動寫錯誤訊息。但是在Flask-WTF中,因為內部重寫了相關方法,導致沒法在不使用Flask-Babel的情況下使用內建的翻譯。問題來了:如果在第4章介紹Flask-Babel和i18n等相關概念的話,這顯然需要佔據大量篇幅,並不合適,而且這部分內容已經計劃加入到第10章。
為此,書的安排沒法改動,那麼只好調整Flask-WTF的內部實現,所以就有了ofollow,noindex">這個PR 。類似的情況還有很多,比如Firefox支援headless模式後,Selenium中卻沒有提供和Chrome相同的匯入介面;Flask-OAuthlib中,傳入access令牌只能使用元組或字典型別,而不能使用更直觀的字串變數傳入……
下面是一些寫作期間提交的開源貢獻:
- GitHub-Flask:Support API endpoint with a leading slash
- Flask-OAuthlib:Add support for string type token
- Selenium:Add import statement for FirefoxOptions
- Authlib:add google_fetch_user function
- Flask-SocketIO:Add missing json argument in send() function
- Flask-OAuthlib:Add support for string type token
- OAuthlib:Check access token in self.token dict
- Flask-Moment:Add auto-detect locale support
- Flask-Whooshee:Fix unicode decode error on Python2
- Pipenv:Add tips for Supervisor user
- Flask-WTF:Add support to change message language
- Werkzeug:Reloader: Force the key of environment variable into string type
- Flask:19 merged PRs, mostly are documentation fix
當然,如果加上其他沒有太大意義的文件更新,這個列表還可以更長。
值得特別說明的是Werkzeug的這個PR,這個PR對應的bug困擾了我很長一段時間。一開始我把問題歸咎到python-dotenv身上,還建立了一個PR(#101 ),但是維護者遲遲沒有回覆。後來再次研究,才發現是Werkzeug的問題,於是建立了#1320 ,然後被lepture用更好的實現取代了(#1321 )。不過,在python-dotenv錯誤建立的那個PR倒是促成了Pipenv的這個PR(#2386 )。
推動釋出新的版本
除了讓PR被合併,還要讓這些專案釋出新的release,這樣才能在專案原始碼公開後,讓讀者可以正常使用。在我的推動下,Flask-OAuthlib、Flask-Whooshee和Flask-Moment都發布了新的版本。
其他的專案,除了Werkzeug以外,大部分都在整個寫作的時間跨度釋出了新的版本。尤其重要的是Flask的1.0版本。從書一開始寫作,我就直接採用了主分支的程式碼,書中我直接將版本號寫為0.13。如果Flask遲遲不釋出新版本,那我會陷入一個很尷尬的境地:要麼大膽採用主分支程式碼,但是可能會出現變動,導致書中的內容不可靠;要麼採用舊版本,那書出版後可能會很快面臨過時的危險。還好,在寫作接近尾聲的4月末,新版本1.0釋出了。
4個Flask擴充套件
用於整合Bootstrap的擴充套件Flask-Bootstrap目前的維護狀態很糟糕:上一次release是17年1月,上一次合併commit是17年3月,而且已經很長時間不再處理PR和Issue。
原專案還存在很多問題:Jinja語法不標準、內建基模板引入不必要的複雜度、分頁巨集不支援傳入URL片段值。除此之外,讓我決定寫新的擴充套件替代它的最主要原因是因為它不支援Bootstrap 4,而我不能接受在書中引入一個這樣過時的專案。
為了解決這些問題,只好寫了Bootstrap-Flask 。最終決定寫替代擴充套件的時候,書已經完成了三分之二,大量舊的內容和原始碼都要改寫。把書稿和原始碼從Flask-Bootstrap和Bootstrap3遷移到Bootstrap-Flask和Bootstrap4是一個非常痛苦的過程,到現在還記憶猶新……
對於某些空白的領域,我寫了三個擴充套件來簡化整合操作:
- Flask-Avatars :頭像處理
- Flask-Dropzone :整合Dropzone.js,提供檔案上傳的客戶端處理
- Flask-CKEditor :整合富文字編輯器CKEditor
5個Flask開源專案
在此之前,完善的Flask開源專案屈指可數,除了Flask官方提供的兩個示例程式外,就只有Miguel Grinberg的兩個程式。而這本書帶來了5個相對比較完善、所有依賴都基於最新版本的開源專案(嚴格來說,第1個程式比較簡單,可以排除在外):