摘要:下一步就是修改視圖。判斷語句的條件有兩個博文的標題圖不是必須的,剔除掉沒有標題圖的文章,這些文章不需要處理圖片。總結本章學習了如何上傳并處理文章的標題圖,從此博客首頁就有了漂亮的外觀。
現在雖然博客的功能大都實現了,但是界面還是比較樸素,特別是首頁的文章列表幾乎全是文字,看多了難免疲勞。因此,給每個文章標題配一張標題圖,不僅美觀,用戶也能通過圖片快速了解文章內容。實際上大部分社交網站也都是這么干的,畢竟人的天性就是懶,能看圖就堅決不看字。
在上傳用戶頭像章節中,我們已經接觸過上傳、展示圖片了。標題圖的實現也差不多,不同的是本章會更近一步,對圖片進行縮放等處理,使頁面整潔美觀、并且高效。
準備工作與用戶頭像類似,標題圖是屬于每篇博文自己的“資產”,因此需要修改model,新建一個字段:
article/models.py class ArticlePost(models.Model): ... # 文章標題圖 avatar = models.ImageField(upload_to="article/%Y%m%d/", blank=True) ...
注意上傳地址中的%Y%m%d是日期格式化的寫法。比如上傳時間是2019年2月26日,則標題圖會上傳到media/article/20190226這個目錄中。
記得數據遷移。
標題圖通常在創建新文章的時候就設置好了,而新文章是通過表單上傳到數據庫中的。因此接下來就是修改發表文章的表單類:
article/forms.py ... class ArticlePostForm(forms.ModelForm): class Meta: ... fields = ("title", "body", "tags", "avatar")
增加了avatar字段而已,沒有新內容。
下一步就是修改視圖。因為POST的表單中包含了圖片文件,所以要將request.FILES也一并綁定到表單類中,否則圖片無法正確保存:
article/views.py ... def article_create(request): if request.method == "POST": # 增加 request.FILES article_post_form = ArticlePostForm(request.POST, request.FILES) ...
很好,功能差不多已經通了,接下來就是對圖片進行處理。
處理圖片寫代碼之前先構思一下需要進行怎樣的處理:
標題圖對畫質沒有太高的要求,因此需要縮小圖片的體積,以便提高網頁的加載速度。
其次還需要對圖片的長寬進行規范化。我比較喜歡將圖片的寬度設置得相同,這樣標題可以比較整齊。
下一個問題是,代碼應該寫到什么地方呢?似乎在model、form或者view里處理圖片都可以。在這里我打算把代碼寫到model中去,這樣不管你在任何地方上傳圖片(包括后臺中!),圖片都會得到處理。
想好之后,就要行動了。還記得Pillow這個庫嗎,我們很早就把它安裝好了,現在是使用它的時候了:
article/models.py ... # 記得導入! from PIL import Image class ArticlePost(models.Model): ... # 前面寫好的代碼 avatar = models.ImageField(upload_to="article/%Y%m%d/", blank=True) # 保存時處理圖片 def save(self, *args, **kwargs): # 調用原有的 save() 的功能 article = super(ArticlePost, self).save(*args, **kwargs) # 固定寬度縮放圖片大小 if self.avatar and not kwargs.get("update_fields"): image = Image.open(self.avatar) (x, y) = image.size new_x = 400 new_y = int(new_x * (y / x)) resized_image = image.resize((new_x, new_y), Image.ANTIALIAS) resized_image.save(self.avatar.path) return article ...
代碼不多,但是有很多細節,值得仔細推敲。不急,一行一行來:
save()是model內置的方法,它會在model實例每次保存時調用。這里改寫它,將處理圖片的邏輯“塞進去”。
super(ArticlePost, self).save(*args, **kwargs)的作用是調用父類中原有的save()方法,即將model中的字段數據保存到數據庫中。因為圖片處理是基于已經保存的圖片的,所以這句一定要在處理圖片之前執行,否則會得到找不到原始圖片的錯誤。
if判斷語句的條件有兩個:
博文的標題圖不是必須的,self.avatar剔除掉沒有標題圖的文章,這些文章不需要處理圖片。
不太好理解的是這個not kwargs.get("update_fields")。還記得article_detail()視圖中為了統計瀏覽量而調用了save(update_fields=["total_views"])嗎?沒錯,就是為了排除掉統計瀏覽量調用的save(),免得每次用戶進入文章詳情頁面都要處理標題圖,太影響性能了。
這種判斷方法雖然簡單,但會造成模型和視圖的緊耦合。讀者在實踐中可探索更優雅的方法,比如專門設置一個參數,用來判斷是哪類視圖調用了save()。
接下來都是Pillow處理圖片的流程了:打開原始圖片,取得分辨率,將新圖片的寬度設置為400并根據比例縮小高度,最后用新圖片將原始圖片覆蓋掉。Image.ANTIALIAS表示縮放采用平滑濾波。
最后一步,將父類save()返回的結果原封不動的返回去。
完美!
模板與測試剩下的工作就比較簡單了。
修改發表文章的模板,讓表單能夠上傳圖片:
templates/article/create.html ......
然后修改文章列表模板,讓其能夠展現標題圖。
為了美觀,這里稍微改動了列表循環的整體結構:
templates/article/list.html ...{% for article in articles %} {% if article.avatar %}{% endfor %}...接下來又是喜聞樂見的測試環節。
啟動服務器,打開發表文章頁面:
選擇幾張分辨率各不相同的圖片作為標題圖,
發表幾篇文章并回到文章列表頁面:
看起來似乎不錯。
查看一下media目錄下實際保存的圖片:
確實保存到想要的目錄下,并且左下角顯示圖片的寬度全都為400了。
掃尾工作功能已經實現了,但還有掃尾工作需要去做:
需要對上傳的圖片做更多的驗證工作,比如上傳的文件是否為圖片、分辨率是否滿足要求。雖然在個人博客項目中這些驗證并不是特別重要,但在其他項目中就說不好了:誰知道用戶會上傳些什么奇奇怪怪的東西?
編輯文章、刪除文章也同樣需要處理上傳的圖片。你還可以將縮放分辨率的技術應用到用戶頭像上,比如裁剪成方形。
注意:刪除數據庫中的avatar條目只是斷開了數據表和圖片的鏈接而已,實際上圖片還保存在原來的位置。要徹底刪除圖片,你還得寫操作系統文件的代碼才行。怎么實現這些功能就不贅述了,留給讀者自己去折騰吧。
輪子雖然本文是自己動手寫的代碼(嚴格說來Pillow也是輪子),但想必你也猜到了,還有更加智能的輪子:django-imagekit,這個庫可以直接繼承到model字段里面,比如這樣:
article/models.py # 引入imagekit from imagekit.models import ProcessedImageField from imagekit.processors import ResizeToFit class ArticlePost(models.Model): ... avatar = ProcessedImageField( upload_to="article/%Y%m%d", processors=[ResizeToFit(width=400)], format="JPEG", options={"quality": 100}, )字段中定義好了上傳位置、處理規則、存儲格式以及圖片質量,你不需要寫任何處理圖片的代碼了。
更多的用法見官方介紹。
總結本章學習了如何上傳并處理文章的標題圖,從此博客首頁就有了漂亮的外觀。
需要指出的是,個人博客所采用的服務器通常性能不佳,用來保存文章縮略圖等小尺寸的圖片倒還好,但是千萬不要存儲大尺寸的圖片文件,否則用戶等待幾分鐘都刷不開你的圖片,那是很悲劇的。
因此建議你將大尺寸的圖片、視頻等放到專業的云對象存儲服務商中,比如七牛云、又拍云等,在你存儲量很小時(10G以內)是花不了多少錢的。
有疑問請在杜賽的個人網站留言,我會盡快回復。
或Email私信我:dusaiphoto@foxmail.com
項目完整代碼:Django_blog_tutorial
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/43260.html
摘要:改寫視圖函數上一章我們感受了視圖的工作流程。循壞表示依次取出中的元素,命名為,并分別執行接下來操作。即為語言,中間包裹了一個段落的文字。有疑問請在杜賽的個人網站留言,我會盡快回復。 改寫視圖函數 上一章我們感受了視圖的工作流程。 為了讓視圖真正發揮作用,改寫article/views.py中的article_list視圖函數: article/views.py from django...
摘要:目前為止我們已經完成了文章的新建刪除以及查看,還剩最后一項,即對已經完成的文章進行修改。總結至此我們就實現了一篇文章的增刪改查四個基礎功能,也算小有成就。有疑問請在杜賽的個人網站留言,我會盡快回復。 目前為止我們已經完成了文章的新建、刪除以及查看,還剩最后一項,即對已經完成的文章進行修改。 實際上修改文章與新建文章有點類似,不同的地方有兩點: 修改是在原有文章的基礎上,因此需要傳遞 ...
摘要:重新打開一個命令行窗口,進入虛擬環境,安裝是一種通用語法高亮顯示器,可以幫助我們自動生成美化代碼塊的樣式文件。 上一章我們實現了文章詳情頁面。為了讓文章正文能夠進行標題、加粗、引用、代碼塊等不同的排版(像在Office中那樣!),我們將使用Markdown語法。 安裝Markdown Markdown是一種輕量級的標記語言,它允許人們使用易讀易寫的純文本格式編寫文檔,然后轉換成有效的或...
摘要:博文也是同樣的,好的目錄對博主和讀者都很有幫助。文中的目錄之前我們已經為博文支持了語法,現在繼續增強其功能。修改文章詳情視圖文章詳情目錄擴展僅僅是將將擴展添加了進去。通過將目錄傳遞給模板。 對會讀書的人來說,讀一本書要做的第一件事,就是仔細閱讀這本書的目錄。閱讀目錄可以對整體內容有所了解,并清楚地知道感興趣的部分在哪里,提高閱讀質量。 博文也是同樣的,好的目錄對博主和讀者都很有幫助。更...
上一章我們的網站頁面實在太粗糙,你肯定不會拿來做真正的博客首頁。因此這章我們要借助Bootstrap的力量,改寫一個大氣的博客。 配置Bootstrap 4 Bootstrap是用于網站開發的開源前端框架(前端指的是展現給最終用戶的界面),它提供字體排印、窗體、按鈕、導航及其他各種組件,旨在使動態網頁和Web應用的開發更加容易。 Bootstrap有幾個版本都比較流行,我們選擇最新版本的Boots...
閱讀 2042·2021-11-19 11:37
閱讀 732·2021-11-11 16:54
閱讀 1181·2021-11-02 14:44
閱讀 3084·2021-09-02 15:40
閱讀 2384·2019-08-30 15:44
閱讀 972·2019-08-29 11:17
閱讀 1074·2019-08-26 14:06
閱讀 1568·2019-08-26 13:47