flask實現web的登錄和註冊:flask web開發實戰源代碼

一、概述

在第二部分中,我將討論如何使用模板。

學習完第一章之後,你已經擁有了一個雖然簡單,但是可以成功運行Web應用,它的文件結構如下:

microblog  
	venv  
	app    
		__init__.py    
		routes.py  
	microblog.py

在終端會話中設置環境變量FLASK_APP=microblog.py,然後執行flask run命令來運行應用。 包含這個應用的Web服務啟動之後,你可以通過在Web瀏覽器的地址欄中鍵入URL http://localhost:5000/ 來驗證。

本章將沿用這個應用,在此之上,你將學習如何生成包含複雜結構和諸多動態組件的網頁。如果對這個應用和相關開發流程有所遺忘,請回顧第一章。

二、什麼是模板?

我設計的微博應用程序的主頁會有一個歡迎用戶的標題。雖然目前的應用程序還沒有實現用戶概念,但這不妨礙我使用一個Python字典來模擬一個用戶,如下所示:

user = {'username':'Miguel'}

創建模擬對象是一項實用的技術,它可以讓你專註於應用程序的一部分,而無需為系統中尚不存在的其他部分分心。 在設計應用程序主頁的時候,我可不希望因為沒有一個用戶系統來分散我的注意力,因此我使用了模擬用戶對象,來繼續接下來的工作。

原先的視圖函數返回簡單的字符串,我現在要將其擴展為包含完整HTML頁面元素的字符串,如下所示:

from app import app 
@app.route('/')
@app.route('/index')
def index():    
	user = {'username': 'Miguel'}    
		return '''
<html>    
     <head>        
      <title>Home Page - Microblog</title>    
			</head>    
<body>        
        <h1>Hello, ''' + user['username'] + '''!</h1>    
</body>
</html>

運行flask run 更新視圖功能,並查看應用程序在瀏覽器中的顯示效果。

二、flask博客項目實戰-之模板使用

利用上述的代碼更新這個視圖函數,然後再次在瀏覽器打開它的URL看看結果。

如果我說這個函數返回HTML的方式並不友好的話,你可能會覺得詫異。設想一下,當這個視圖函數中的用戶和博客不斷變化時,裡面的代碼將會變得多麼的複雜。應用的視圖函數及其關聯的URL也會持續增長。如果哪天我決定更改這個應用的布局,那就不得不更新每個視圖函數的HTML字符串。顯然,隨着應用的擴張,這種方式完全不可行。

將應用程序的後台邏輯和網頁布局劃分開來,你不覺得更容易組織管理嗎?甚至你可以聘請一位Web設計師來設計一個殺手級的網站前端,而你只需要用Python編寫後台應用邏輯。

模板有助於實現頁面展現和業務邏輯之間的分離。 在Flask中,模板被編寫為單獨的文件,存儲在應用程序包內的templates文件夾中。 在確定你在microblog目錄後,創建一個存儲模板的目錄:

在Flask中,模板是作為單獨的文件編寫的,存放在應用程序 包內的 templates文件夾(約定俗成命名為 templates)下。

即在app目錄下創建templates文件夾:

# mkdir templates

在下面可以看到你的第一個模板,它的功能與上面的index()視圖函數返回的HTML頁面相似。 把這個文件寫在app/templates/index.html中:

<html>    
  <head>        
  	<title>{{ title }} - Microblog</title>    
	</head>    
<body>        
      <h1>Hello, {{ user.username }}!</h1>    
</body>
</html>

這是一個標準的、簡單的HTML頁面。但有一點跟我們寫HTML代碼不同是title標籤、h1標籤中的 {{ … }}兩對花括號,在此它是個 佔位符,作用是將表達式(如文字、數學式子、比較運算符等,其實在Python中是一個Python語句)打印到模板進行輸出。具體參考Jinja2官網文檔。
這些佔位符表示HTML頁面中可變的部分,並且只在運行時才知道。

這個HTML頁面看起來非常簡單,唯一值得關注的地方是{{ … }}。{{ … }}包含的內容是動態的,只有在運行時才知道具體表示成什麼樣子。

網頁渲染轉移到HTML模板之後,視圖函數就能被簡化:
現在HTML頁面的呈現已在HTML模板中了,這樣接着就可簡化一下視圖函數index()了。修改routes.py文件
app/routes.py:使用render_template()函數

from app import appfrom flask import render_template             #從flask包中導入render_template函數 
 @app.route('/')
@app.route('/index')
def index():
	user = {'username':'Miguel'}    
	return render_template('index.html', title='Home', user=user)

將模板(index.html)轉換為完整HTML頁面的操作稱之為 呈現(render,譯作 遞交、表達、給予,在此譯作 “渲染”)。為了渲染模板,由從flask包中導入的render_template()完成,此函數“攜帶”模板文件名(index.html)、模板參數的變量列表,並返回相同的模板,不過其中所有佔位符都替換為實際值。

看起來好多了吧? 趕緊試試這個新版本的應用程序,看看模板是如何工作的。 在瀏覽器中加載頁面後,你需要從瀏覽器查看HTML源代碼並將其與原始模板進行比較。

render_template()函數調用Flask框架原生依賴的Jinja2模板引擎。 Jinja2用render_template()函數傳入的參數中的相應值替換{{…}}塊。

控制結構—-if條件、for循環、繼承

上述過程只是理解了:Jinja2模板引擎 如何在渲染過程中用實際值 替換 (模板中的)佔位符。
接下來將認識到更多 Jinja2在模板文件中支持的更多強大操作:if條件、for循環、繼承等。
源自官網的這句話:

There are a few kinds of delimiters. The default Jinja delimiters are configured as follows: 
{% ... %} for Statements
{{ ... }} for Expressions to print to the template output
{# ... #} for Comments not included in the template output
#  ... ## for Line Statements

if、for、繼承均在{% … %}塊中寫控制語句。
if條件
形如:

{% if title %}            
  ...語句塊        
{% else %}            
  ...語句塊        
{% endif %}

app/templates/index.html:模板中添加條件語句

<html>    
  <head>        
	  {% if title %}            
			<title>{{ title }} - Microblog</title>        
		{% else %}            
      <title>Welcome to Microblog!</title>        
    {% endif %}    
  </head>    
   <body>        
    <h1>Hello,{{ user.username }}!</h1>    
  </body>
</html>

上述代碼中if語句塊的功能是:若視圖函數index()沒有傳遞title佔位符變量的值,則index.html模板將會提供默認值(else語句塊中),而不是顯示空標題。
嘗試將routes.py中render_template()中的title=’Home’,刪除。效果:圖略

for循環
在模板中形如:

{% for post in posts %}    
  ...語句塊
{% endfor %}

需求:登錄用戶可在主頁中查看最新的帖子。
實現:
首先,用虛擬對象的方法來創建一些用戶、帖子,以供顯示。
app/routes.py:視圖函數中的假帖子

from app import appfrom flask import render_template#從flask包中導入render_template函數 
@app.route('/')
@app.route('/index')
def index():    
	user = {'username':'Miguel'}#用戶    
  posts = [#創建一個列表:帖子。裡面元素是兩個字典,每個字典里元素還是字典,分別作者、帖子內容。        
           {            
           'author': {'username':'John'},            
           'body':'Beautiful day in Portland!'},        
           {            
            'author': {'username':'Susan'},            
            'body':'The Avengers movie was so cool!'        
           }
					 ]    
           return render_template('index.html', title='Home', user=user, posts=posts)

帖子列表 可包含任意數量的元素,由視圖函數index()決定將在頁面中顯示的帖子數量。而模板index.html不能假設這有多少個帖子,因此它需要準備好以通用方式呈現視圖發送來的儘可能多的帖子。在模板index.html中,用for循環遍歷所有的帖子並呈現。
app/templates/index.html:在模板中的for循環

<html>    
  <head>        
  {% if title %}            
		<title>{{ title }} - Microblog</title>        
  {% else %}            
    <title>Welcome to Microblog!</title>        
  {% endif %}    
   </head>    
  <body>        
     <h1>Hello,{{ user.username }}!</h1>        
  {% for post in posts %}            
    <div><p>{{ post.author.username }} says: <b>{{ post.body }}</b></p></div>        
	{% endfor %}    
 </body>
</html>

模板繼承
形如:

{% extends "base.html" %} 
{% block content %}    
  ...
{% endblock %}

現在,大部分Web應用程序在頁面頂部有一個導航欄,它常包含一些常用鏈接:如登錄、退出、編輯個人資料等。可以很輕鬆地將導航欄添加到index.html模板,甚至更多的HTML頁面中。但隨着應用程序的增長(頁面數量的增多),這些頁面都將使用相同的導航欄,不可能每一個頁面都增加一份相同的導航欄代碼。

Jinja2具有模板繼承功能,完美解決上述問題。在實際操作中,將所有模板共有的頁面布局部分移至基礎模板中,其他模板則繼承自它。

實例:實現一個簡單的導航欄,其他模板繼承它。
在app/templates目錄下創建一個基礎模板文件 base.html。
app/templates/base.html:帶導航欄的基礎模板

<html>    
  <head>        
  {% if title %}            
		<title>{{ title }} - Microblog</title>        
	{% else %}            
    <title>Welcome to Microblog</title>        
  {% endif %}    
   </head>    
   <body>        
     <div>Microblog:<a href="/index">Home</a></div>        <hr>        
     {% block content %}        
   	{% endblock %}    
    </body>
 </html>

在上述基礎模板中,塊block 控制語句用於定義派生模板可自行插入的位置。塊block 被賦予唯一的名字 content,派生模板在提供其內容時可引用這個名稱。

修改index.html這個模板,讓其繼承base.html模板。
app/templates/index.html:從基礎模板繼承

{% extends "base.html" %} 
{% block content %}    
  <h1>Hello,{{ user.username }}!</h1>    
{% for post in posts %}        
  <div><p>{{ post.author.username }} says: <b>{{ post.body }}</b></p></div>    
{% endfor %}
{% endblock %}

base.html基礎模板 實現處理常規頁面的結構,則派生模板index.html簡化大部分內容。
extends語句 建立了兩個模板之間的繼承關係,因此,Jinja2就會知道:當它被要求渲染index.html時,需要將其嵌入base.html中。這倆模板具有匹配的block語句 名稱content,這就是Jinja2如何將兩個模板合併為一個模板的方法。

二、flask博客項目實戰-之模板使用

今後,當再需要為應用程序創建其他頁面時,就可省去編寫相同代碼的麻煩,並讓應用程序的所有頁面共享相同的外觀,而只需一個步驟:創建繼承自base.html模板的派生模板。

目前為止,項目結構:

microblog/    
  venv/    
  app/        
  templates/            
  			base.html            
				index.html        
	__init__.py        
	routes.py    
	microblog.py

原創文章,作者:投稿專員,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/222376.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
投稿專員的頭像投稿專員
上一篇 2024-12-09 14:09
下一篇 2024-12-09 14:09

相關推薦

發表回復

登錄後才能評論