在 Flask 應用程式中,我們可以利用訊息閃現機制,在使用者完成特定操作後,提供即時的反饋訊息,例如在新增、修改或刪除資料後,顯示成功或失敗的提示。這能有效提升使用者經驗,讓使用者清楚知道操作結果。此外,資料函式庫搜尋功能也是 Web 應用程式不可或缺的一部分,透過 SQLAlchemy 可以輕鬆地根據不同條件篩選資料,並將結果呈現給使用者。同時,WTForms 提供了簡潔易用的方式來建立和管理 Web 表單,有效簡化表單處理流程,並確保資料的有效性和安全性。結合這些技術,可以開發更完善、使用者友善的 Web 應用程式。
提升使用者經驗:訊息閃現功能實作
在開發高品質的Web應用程式時,提供使用者適當的互動反饋至關重要。當使用者完成某項操作,例如建立新產品並被重新導向至該產品頁面時,適時地告知使用者操作結果是一種良好的實踐。本篇內容將介紹如何使用訊息閃現(Flash Messages)機制來提升使用者經驗。
準備工作
首先,我們需要在現有的產品目錄應用程式中加入訊息閃現功能。同時,必須為應用程式設定一個秘密金鑰(Secret Key),因為Session機制依賴於此金鑰,否則在嘗試閃現訊息時應用程式將會報錯。
實作步驟
1. 設定秘密金鑰
在 flask_catalog_template/my_app/__init__.py 檔案中為應用程式新增一個秘密金鑰:
app.secret_key = 'some_random_key'
2. 修改產品建立處理函式
接下來,在 flask_catalog_template/my_app/catalog/views.py 檔案中修改 create_product() 處理函式,以便在成功建立產品後向使用者閃現一則訊息。同時,這個函式現在支援透過網頁表單建立產品的功能,這使得示範訊息閃現的效果更加直觀。
@catalog.route('/product-create', methods=['GET', 'POST'])
def create_product():
if request.method == 'POST':
name = request.form.get('name')
price = request.form.get('price')
categ_name = request.form.get('category')
category = Category.query.filter_by(name=categ_name).first()
if not category:
category = Category(categ_name)
product = Product(name, price, category)
db.session.add(product)
db.session.commit()
flash('The product %s has been created' % name, 'success')
return redirect(url_for('catalog.product', id=product.id))
return render_template('product-create.html')
在上述程式碼中,當成功建立產品後,會呼叫 flash() 函式閃現一則訊息。第一個引數是訊息內容,第二個引數是訊息類別,可以根據這個類別決定要顯示的提示訊息型別。
3. 新增產品建立表單範本
新增一個名為 product-create.html 的範本檔案,位於 flask_catalog_template/my_app/templates/ 目錄下,用於渲染產品建立表單。
{% extends 'home.html' %}
{% block container %}
<div class="top-pad">
<form class="form-horizontal" method="POST" action="{{ url_for('catalog.create_product') }}" role="form">
<!-- 表單內容省略 -->
<button type="submit" class="btn btn-default">Submit</button>
</form>
</div>
{% endblock %}
4. 修改基礎範本以顯示閃現訊息
最後,修改基礎範本 base.html,使其能夠顯示閃現的訊息。在 <div class="container"> 內部、 {% block container %} 之前加入以下程式碼:
<br/>
<div>
{% for category, message in get_flashed_messages(with_categories=true) %}
<div class="alert alert-{{category}} alert-dismissable">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
{{ message }}
</div>
{% endfor %}
</div>
這段程式碼利用 get_flashed_messages() 函式取得所有閃現的訊息,並根據訊息類別顯示對應的提示框。
結果示範
存取 http://127.0.0.1:5000/product-create 並填寫產品建立表單,提交後將重新導向至新建立的產品頁面,並在頁面頂部顯示一則成功建立產品的提示訊息。
資料函式庫搜尋功能的實作
在Web應用程式中,能夠根據特定條件搜尋資料函式庫記錄是一項基本需求。本文將介紹如何在SQLAlchemy中實作基本的資料函式庫搜尋功能。
實作搜尋功能
在 flask_catalog_template/my_app/catalog/views.py 中新增一個處理函式,用於根據不同條件搜尋產品:
from sqlalchemy.orm import join
@catalog.route('/product-search')
@catalog.route('/product-search/<int:page>')
def product_search(page=1):
name = request.args.get('name')
price = request.args.get('price')
company = request.args.get('company')
category = request.args.get('category')
products = Product.query
# #### 內容解密:
# 這裡根據不同的搜尋條件逐步過濾產品查詢結果。
# 如果提供了名稱,則使用名稱進行模糊搜尋。
if name:
products = products.filter(Product.name.like('%' + name + '%'))
# 如果提供了價格,則精確比對該價格的產品。
if price:
products = products.filter(Product.price == price)
# 如果提供了公司名稱,則對公司名稱進行模糊搜尋。
if company:
products = products.filter(Product.company.like('%' + company + '%'))
# 如果提供了類別,則透過Join操作與Category表進行關聯查詢。
if category:
products = products.select_from(join(Product, Category)).filter(Category.name.like('%' + category + '%'))
# 將最終的查詢結果分頁顯示。
return render_template('products.html', products=products.paginate(page, 10))
使用搜尋功能
可以透過存取類別似 http://127.0.0.1:5000/product-search?name=iPhone 的URL來搜尋名稱包含 “iPhone” 的產品。使用者可以根據不同的條件組合進行搜尋,例如價格、公司名稱或類別等。
使用WTForms建立Web表單
表單處理是任何Web應用程式的重要組成部分。在許多情況下,表單的存在對於Web應用程式至關重要,例如使用者需要登入或提交某些資料,或應用程式需要使用者輸入資料。表單的驗證與表單本身一樣重要,甚至更為重要。以互動方式向使用者呈現這些資訊可以為應用程式增加很多價值。
設計和實作表單
有多種方法可以在Web應用程式中設計和實作表單。隨著Web應用程式的發展,表單驗證和向使用者傳達正確的訊息變得非常重要。可以使用JavaScript和HTML5在前端實作客戶端驗證。伺服器端驗證在為應用程式新增安全性方面發揮著更重要的作用,而不是使用者互動。伺服器端驗證可以防止錯誤的資料進入資料函式庫,從而遏制詐欺和攻擊。
WTForms的功能
WTForms提供了許多預設的欄位和伺服器端驗證,從而提高了開發速度並減少了整體工作量。它還提供了編寫自定義驗證和自定義欄位的靈活性。
安裝Flask-WTF
本章將使用一個名為Flask-WTF的Flask擴充套件,它提供了WTForms和Flask之間的整合,負責處理一些重要且瑣碎的事情,使我們的應用程式更加安全和有效。可以透過以下命令安裝它:
$ pip install Flask-WTF
將SQLAlchemy模型資料表示為表單
首先,我們將使用SQLAlchemy模型建立一個表單。在這個範例中,我們將使用本文前面使用的產品模型,並新增功能,透過Web表單建立產品。
準備工作
我們將使用第4章《Working with Views》中使用的目錄應用程式,並為Product模型開發一個表單。
實作步驟
如果您回憶一下,Product模型在models.py檔案中如下所示:
class Product(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(255))
price = db.Column(db.Float)
category_id = db.Column(db.Integer, db.ForeignKey('category.id'))
category = db.relationship('Category', backref=db.backref('products', lazy='dynamic'))
首先,我們將在models.py中建立一個ProductForm類別,它將繼承自flask_wtf提供的FlaskForm類別,以表示Web表單所需的欄位:
from wtforms import StringField, DecimalField, SelectField
from flask_wtf import FlaskForm
class ProductForm(FlaskForm):
name = StringField('Name')
price = DecimalField('Price')
category = SelectField('Category', coerce=int)
程式碼解析:
from wtforms import StringField, DecimalField, SelectField
from flask_wtf import FlaskForm
class ProductForm(FlaskForm):
name = StringField('Name')
price = DecimalField('Price')
category = SelectField('Category', coerce=int)
內容解密:
- 匯入必要的模組:從
wtforms匯入StringField、DecimalField和SelectField,從flask_wtf匯入FlaskForm。 - 定義ProductForm類別:該類別繼承自
FlaskForm,用於表示Web表單。 name欄位:使用StringField型別,表示需要文字資料的欄位。price欄位:使用DecimalField型別,將資料解析為Python的Decimal資料型別。category欄位:使用SelectField型別,表示只能從先前建立的類別中選擇的欄位。coerce=int引數表示將傳入的資料強制轉換為整數值。
views.py中的create_product()處理函式現在應該容納前面建立的表單:
from my_app.catalog.models import ProductForm
@catalog.route('/product-create', methods=['GET', 'POST'])
def create_product():
form = ProductForm(meta={'csrf': False})
categories = [(c.id, c.name) for c in Category.query.all()]
form.category.choices = categories
if request.method == 'POST':
name = request.form.get('name')
price = request.form.get('price')
category = Category.query.get_or_404(request.form.get('category'))
product = Product(name, price, category)
db.session.add(product)
db.session.commit()
flash('The product %s has been created' % name, 'success')
return redirect(url_for('catalog.product', id=product.id))
return render_template('product-create.html', form=form)
程式碼解析:
from my_app.catalog.models import ProductForm
@catalog.route('/product-create', methods=['GET', 'POST'])
def create_product():
form = ProductForm(meta={'csrf': False})
categories = [(c.id, c.name) for c in Category.query.all()]
form.category.choices = categories
if request.method == 'POST':
name = request.form.get('name')
price = request.form.get('price')
category = Category.query.get_or_404(request.form.get('category'))
product = Product(name, price, category)
db.session.add(product)
db.session.commit()
flash('The product %s has been created' % name, 'success')
return redirect(url_for('catalog.product', id=product.id))
return render_template('product-create.html', form=form)
內容解密:
- 匯入ProductForm:從
my_app.catalog.models匯入ProductForm。 - 定義create_product函式:處理
/product-create路由,支援GET和POST方法。 - 建立ProductForm例項:停用CSRF保護。
- 取得類別列表:查詢所有類別並將其格式化為列表。
- 設定類別選項:將類別列表指定給表單的
category欄位。 - 處理POST請求:取得表單資料,建立新產品並提交到資料函式庫。
- 顯示成功訊息並重定向:建立成功後顯示訊息並重定向到產品頁面。
- 渲染表單頁面:如果是GET請求,渲染包含表單的頁面。