前面咱們已經學會如何用Markdown語法書寫文章了。html
可是還有問題呀。以前寫文章都是在後臺中進行的,萬一有別的普通用戶也要發表文章怎麼辦?萬一我想拓展些後臺中沒有的提交驗證功能又怎麼辦?python
本章即講述如何在前臺中提交新的文章,以便知足開發者各類各樣的特殊需求。git
在HTML中,表單是在 <form>...</form>
中的一些元素,它容許訪客作相似輸入文本、選擇選項、操做對象或空間等動做,而後發送這些信息到服務端。一些表單界面元素(文本框或複選框)很是簡單並內置在HTML中,而其餘會複雜些:像彈出日期選擇等操做控件。程序員
處理表單是一件挺複雜的事情。想一想看Django的admin,許多不一樣類型的數據可能須要在一張表單中準備顯示,渲染成HTML,使用方便的界面進行編輯,傳到服務器,驗證和清理數據,而後保存或跳過進行下一步處理。github
Django的表單功能能夠簡化上述工做的大部份內容,而且也能比大多數程序員本身編寫代碼去實現來的更安全。數據庫
Django表單系統的核心組件是 Form
類,它可以描述一張表單並決定它如何工做及呈現。django
要使用Form
類也很簡單,須要在article/
中建立forms.py
文件,並寫入以下代碼:瀏覽器
article/forms.py # 引入表單類 from django import forms # 引入文章模型 from .models import ArticlePost # 寫文章的表單類 class ArticlePostForm(forms.ModelForm): class Meta: # 指明數據模型來源 model = ArticlePost # 定義表單包含的字段 fields = ('title', 'body')
代碼中ArticlePostForm
類繼承了Django的表單類forms.ModelForm
,並在類中定義了內部類class Meta
(以前提到過,還記得嗎),指明瞭數據模型的來源,以及表單中應該包含數據模型的哪些字段。安全
在ArticlePost
模型中,created
和updated
字段爲自動生成,不須要填入;author
字段暫時固定爲id=1的管理員用戶,也不用填入;剩下的title
和body
就是表單須要填入的內容了。服務器
接下來,改寫article/views.py
,添加一個視圖函數以處理寫文章的請求:
article/views.py ... # 引入redirect重定向模塊 from django.shortcuts import render, redirect # 引入HttpResponse from django.http import HttpResponse # 引入剛纔定義的ArticlePostForm表單類 from .forms import ArticlePostForm # 引入User模型 from django.contrib.auth.models import User ... # 寫文章的視圖 def article_create(request): # 判斷用戶是否提交數據 if request.method == "POST": # 將提交的數據賦值到表單實例中 article_post_form = ArticlePostForm(data=request.POST) # 判斷提交的數據是否知足模型的要求 if article_post_form.is_valid(): # 保存數據,但暫時不提交到數據庫中 new_article = article_post_form.save(commit=False) # 指定數據庫中 id=1 的用戶爲做者 new_article.author = User.objects.get(id=1) # 將新文章保存到數據庫中 new_article.save() # 完成後返回到文章列表 return redirect("article:article_list") # 若是數據不合法,返回錯誤信息 else: return HttpResponse("表單內容有誤,請從新填寫。") # 若是用戶請求獲取數據 else: # 建立表單類實例 article_post_form = ArticlePostForm() # 賦值上下文 context = { 'article_post_form': article_post_form } # 返回模板 return render(request, 'article/create.html', context)
分析一下上面的代碼。當視圖函數接收到一個客戶端的request
請求時,首先根據request.method
判斷用戶是要提交數據(POST)、仍是要獲取數據(GET):
若是用戶是提交數據,將POST給服務器的表單數據賦於article_post_form
實例。
而後使用Django內置的方法.is_valid()
判斷提交的數據是否知足模型的要求。
commit=False
暫時不提交到數據庫,由於author
還未指定),並指定author
爲id=1的管理員用戶。而後提交到數據庫,並經過redirect
返回文章列表。redirect
可經過url地址的名字,反向解析到對應的url。其實邏輯並不複雜,不明白的讀者請逐句理解。
這裏特別提醒Django中的縮進不可以空格和tab鍵混用,不然會報錯。因爲不一樣的編輯器對tab的顯示不盡相同,所以你應該堅持使用空格鍵縮進。
寫好視圖以後,就須要寫模板文件了。在templates/article/
中建立create.html
:
templates/article/create.html <!-- extends代表此頁面繼承自 base.html 文件 --> {% extends "base.html" %} {% load staticfiles %} <!-- 寫入 base.html 中定義的 title --> {% block title %} 寫文章 {% endblock title %} <!-- 寫入 base.html 中定義的 content --> {% block content %} <!-- 寫文章表單 --> <div class="container"> <div class="row"> <div class="col-12"> <br> <!-- 提交文章的表單 --> <form method="post" action="."> <!-- Django中須要POST數據的地方都必須有csrf_token --> {% csrf_token %} <!-- 文章標題 --> <div class="form-group"> <!-- 標籤 --> <label for="title">文章標題</label> <!-- 文本框 --> <input type="text" class="form-control" id="title" name="title"> </div> <!-- 文章正文 --> <div class="form-group"> <label for="body">文章正文</label> <!-- 文本區域 --> <textarea type="text" class="form-control" id="body" name="body" rows="12"></textarea> </div> <!-- 提交按鈕 --> <button type="submit" class="btn btn-primary">完成</button> </form> </div> </div> </div> {% endblock content %}
html文件仍是一如既往的長。再重複一次,看不懂html文件語法也沒有關係,先照着抄一遍,之後再慢慢理解,不影響目前Django的學習。
對其中的新內容進行審視:
<form>..</form>
標籤中的內容就是須要提交的表單。method="post"
指定了表單提交的方式爲POST(與視圖函數中的request.method
相聯繫);action="."
指定了表單提交的地址爲默認的當前url。{% csrf_token %}
,它是Django中一個與網絡安全相關的中間件驗證。目前咱們暫時不去深究它的實現,只須要知道表單中必須包含它就能夠了,不然將會獲得一個403錯誤。<input>
和<textarea>
標籤中的name=''
屬性指定了當前文本框提交的數據的名稱,它必須與表單類中的字段名稱對應,不然服務器沒法將字段和數據正確的對應起來。最後老規矩,在article/urls.py
中增長一個寫文章的url地址:
article/urls.py urlpatterns = [ ... # 寫文章 path('article-create/', views.article_create, name='article_create'), ]
大功告成了,不要着急,先喝口水,萬一有bug又得忙活半天了。若是報錯也不要慌張,開發過程必定是曲折的,耐心看看Django給出的錯誤提示,線索就在其中。
保存修改並運行服務器,地址欄中輸入:http://127.0.0.1:8000/article/article-create/
,看到以下界面:
很好,彷佛正常工做起來了。接着隨便輸入些Markdown語法的文章,測試功能是否正常:
點擊完成按鈕後,頁面會回到文章列表:
剛纔提交的文章神奇的出如今列表中了。
點擊閱讀本文按鈕,進入文章詳情頁面:
出現了具備Markdown語法的一篇優美的文章。
使用Django編寫博客是否是很是有成就感呢?
別激動,還有一些收尾工做須要作。
與以前相似,咱們須要在導航欄中設置一個寫文章的入口,優化使用體驗。
將下列代碼加入到templates/header.html
中:
<li class="nav-item"> <a class="nav-link" href="{% url 'article:article_create' %}">寫文章</a> </li>
讀者是否清楚,上面的代碼應該放置在什麼位置呢?
保存後刷新瀏覽器界面,導航欄有了以下變化:
點擊寫文章按鈕,就能夠進入寫新文章的頁面了,今後不再用手動輸入繁瑣的url地址了。
世界是多麼的美好。
本章學習了使用Django的表單類,完成了提交新文章的基本功能。固然目前暫時尚未真正將文章和登陸的用戶關聯起來;等到學習了用戶管理的知識,再回頭來處理這部分的內容。
下一章繼續學習如何刪除一篇文章。
轉載請告知做者並註明出處。