摘要:我們現在開始設計發布問答的界面與功能現在點擊它還是沒有反應的,我們要設計一個問答界面的,然后把發布問答鏈接過去。
我們現在開始設計發布問答的界面與功能:
現在點擊它還是沒有反應的,我們要設計一個問答界面的html,然后把發布問答鏈接過去。
首先編寫一個視圖函數如下:
@app.route("/question/") def question(): return render_template("question.html")
在base.html中為發布問答添加鏈接:
問答頁面的html首先也要繼承導航條,然后主要界面設計如下:
這里還是利用css加Bootstrap樣式完成的,問題描述區域是一個textarea,就不演示代碼了,我個人的經驗是,對于html的排版,要理解盒子模型,借助border來查看元素的邊框,去看看margin和padding的寬度,排版好了之后把邊框去掉。
接下來是內容的提交,為視圖函數提交POST方法,并把提交的內容寫入數據庫,修改question視圖函數,如下:
@app.route("/question/", methods=["GET", "POST"]) def question(): if request.method == "GET": return render_template("question.html") else: question_title = request.form.get("question_title") question_desc = request.form.get("question_desc") author_id = Users.query.filter(Users.username == session.get("username")).first().id new_question = Questions(title=question_title, content=question_desc, author_id=author_id) db.session.add(new_question) db.session.commit() return redirect(url_for("home"))
這里其實與用戶注冊的原理是一致的,此時已經能把填寫的問題內容保存到數據庫了。需要注意的就是,新建一個question對象時,不僅需要title和content,還需要帶上question對應的author_id,因為當初創建模型時這就是個非空字段。
代碼中我們直接用session中的username去Users模型中檢索,來得到author_id,看著很麻煩,而且在很多視圖函數中,我們都需要用到當前登錄用戶的信息,因此可以使用@app.before_request這個鉤子函數,看其名字就很好理解,是在request之前會自動運行的,我們在每次請求之前(或者說每次運行視圖函數之前),都通過鉤子函數來得到當期登錄用戶的User對象(而不是僅僅是session中的username),然后在需要的地方使用它,代碼如下:
@app.before_request def my_before_request(): username = session.get("username") if username: g.user = Users.query.filter(Users.username == username).first()
這個鉤子函數,從session中獲取當前登陸的username,如果獲取到了,再去檢索Users模型,把返回的user對象存入到g對象中,在視圖函數中我們就可以直接使用這個user對象的id/register_time等字段了。此時前面的視圖函數中的
author_id = Users.query.filter(Users.username == session.get("username")).first().id
可以修改成
author_id = g.user.id
此外,發布問題也需要用戶先登錄才可以,如果用戶未登錄,@app.before_request無法獲取到session中的username,此時g對象就沒有user這個屬性,因此我們再次把question視圖修改如下:
@app.route("/question/", methods=["GET", "POST"]) def question(): if request.method == "GET": return render_template("question.html") else: if hasattr(g, "user"): question_title = request.form.get("question_title") question_desc = request.form.get("question_desc") author_id = g.user.id new_question = Questions(title=question_title, content=question_desc, author_id=author_id) db.session.add(new_question) db.session.commit() return redirect(url_for("home")) else: flash("請先登錄") return redirect(url_for("login"))
如果提交的時候未登錄,則跳轉到登陸頁面,并且flash"請先登錄"的提示。其實也可以直接在get方法的時候就直接跳轉,避免用戶寫完了內容,又發現未登錄,頁面跳轉導致內容丟失。我們先把框架搭起來,以后再逐步完善細節。
再注意到我們之前寫的@app.context_processor上下文管理器,也是從session中取對象的,此時我們可以直接借用鉤子函數中的數據里,因此將其改寫如下:
@app.context_processor def my_context_processor(): if hasattr(g, "user"): return {"login_user": g.user} return {}
我們之前說過因為g對象不能跨請求使用,因此在上下文管理器中用的是session,為什么這里又用了g對象呢?原因是現在有了鉤子函數,每次請求都會執行鉤子函數,向g對象中寫入user,所以上下文管理器一直都能從g對象中取到user,不管這個g對象是屬于哪次請求的。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/41259.html
摘要:什么是請求鉤子說白了,就是在執行視圖函數前后你可以進行一些處理,使用裝飾器為我們提供了注冊通用函數的功能。 什么是請求鉤子?說白了,就是在執行視圖函數前后你可以進行一些處理,Flask使用裝飾器為我們提供了注冊通用函數的功能。 before_first_request:在處理第一個請求前執行 before_request:在每次請求前執行 after_request:每次請求之后調用...
摘要:每天的內容跑起來模板引擎表單文件上傳郵件發送一框架的簡介模型負責數據的操作視圖負責數據的展示控制器控制你的的操作以及視圖模板的渲染在中叫做模型負責數據的操作控制你的的操作以及視圖模板的渲染業務邏輯的操作模板負責數據的展示二架構三概念是 flask 每天的內容 flask跑起來 模板引擎 flask表單 文件上傳郵件發送 flask-sqlalchemy 一、web框架的簡介 M ...
摘要:開發實戰筆記安裝和使用虛擬環境虛擬環境是解釋器的一個私有副本,在這個環境中你可以安裝私有的包,而且不會影響系統中安裝的全局的解釋器。處理和函數之間關系的程序稱為路由。例如在請求開始時,我們需要創建數據庫連接或認證發起請求的用戶。 幾天前和同事一起喝酒,大家談到為什么開始讀書這件事。這里所說的讀書不是專業的書籍,而是一些閑書。結果發現原來我們開始讀書的原因很功利。都是因為生活中遇到了困...
閱讀 3049·2021-11-18 10:02
閱讀 3315·2021-11-02 14:48
閱讀 3384·2019-08-30 13:52
閱讀 528·2019-08-29 17:10
閱讀 2071·2019-08-29 12:53
閱讀 1392·2019-08-29 12:53
閱讀 1018·2019-08-29 12:25
閱讀 2155·2019-08-29 12:17