- Web2py 教程
- Web2py - 首頁
- Web2py - 簡介
- Web2py - Python 語言
- Web2py - 框架概述
- Web2py - 核心
- Web2py - 檢視
- Web2py - 資料庫抽象層
- Web2py - 表單 & 驗證器
- Web2py - 郵件 & 簡訊
- Web2py - 訪問控制
- Web2py - 服務
- Web2py - 新增 Ajax 效果
- Web2py - 元件
- Web2py - 部署
- Web2py - 安全性
- Web2py 有用資源
- Web2py 快速指南
- Web2py - 有用資源
- Web2py - 討論
Web2py 快速指南
Web2py - 簡介
web2py 定義為一個免費的、開源的敏捷開發 Web 框架,涉及資料庫驅動的 Web 應用程式;它用 Python 編寫,並可以用 Python 程式設計。它是一個全棧框架;它包含構建一個完全功能的 Web 應用程式所需的所有必要元件。
web2py 框架遵循模型-檢視-控制器模式執行 Web 應用程式,這與傳統的模式不同。
模型是應用程式的一部分,其中包含資料邏輯。模型中的物件用於從資料庫中檢索和儲存資料。
檢視是應用程式的一部分,它有助於將資料顯示呈現給終端使用者。資料顯示是從模型中獲取的。
控制器是應用程式的一部分,它處理使用者互動。控制器可以讀取檢視中的資料,控制使用者輸入,並將輸入資料傳送到特定的模型。
web2py 具有管理 Cookie 和會話的內建功能。在提交事務(以 SQL 術語)後,會話也會同時儲存。
web2py 能夠在完成某些操作後以預定的時間間隔執行任務。這可以透過CRON實現。
web2py – 工作流程
請檢視以下工作流程圖。
工作流程圖如下所述。
模型、檢視和控制器元件構成了使用者 web2py 應用程式。
可以在 web2py 的同一例項中託管多個應用程式。
瀏覽器將 HTTP 請求傳送到伺服器,伺服器與模型、控制器和檢視互動以獲取必要的輸出。
箭頭表示與資料庫引擎的通訊。資料庫查詢可以用原始 SQL 編寫,也可以使用 web2py 資料庫抽象層(將在後面的章節中討論)編寫,以便web2py 應用程式程式碼獨立於任何資料庫引擎。
模型建立與資料庫的資料庫連線並與控制器互動。另一方面,控制器與檢視互動以呈現資料顯示。
排程程式將 HTTP 響應中給定的請求 URL 對映到控制器中的函式呼叫。函式的輸出可以是字串或雜湊表。
資料由檢視呈現。如果使用者請求 HTML 頁面(預設值),則資料將呈現為 HTML 頁面。如果使用者以 XML 格式請求同一頁面,web2py 會嘗試查詢可以以 XML 格式呈現字典的檢視。
web2py 支援的協議包括 HTML、XML、JSON、RSS、CSV 和 RTF。
模型-檢視-控制器
web2py 的模型-檢視-控制器表示如下:
模型
"db.py" is the model:
db = DAL('sqlite://storage.sqlite')
db.define_table(employee, Field('name'), Field(‘phone’))
模型包含應用程式資料的邏輯。它連線到如上圖所示的資料庫。假設正在使用 SQLite 並且儲存在storage.sqlite檔案中,其中定義了一個名為 employee 的表。如果表不存在,web2py 會透過建立相應的表來提供幫助。
控制器
程式"default.py"是控制器。
def employees(): grid = SQLFORM.grid(db.contact, user_signature = False) return locals()
在web2py中,URL 對映有助於訪問函式和模組。對於以上示例,控制器包含一個名為 employees 的單個函式(或“操作”)。
控制器採取的操作返回一個字串或一個 Python 字典,它是一組鍵值對,包括一組區域性變數。
檢視
"default/contacts.html"是檢視。
{{extend 'layout.html'}}
<h1>Manage My Employees</h1>
{{=grid}}
對於給定的示例,檢視在關聯的控制器函式執行後顯示輸出。
此檢視的目的是呈現字典中的變數,這些變數採用 HTML 格式。檢視檔案是用 HTML 編寫的,但它使用{{ 和 }}分隔符嵌入 Python 程式碼。
嵌入到 HTML 中的程式碼包含字典中的 Python 程式碼。
開始使用 web2py
web2py 以二進位制包的形式提供,適用於所有主要的作業系統,如 Windows、UNIX 和 Mac OS X。
安裝 web2py 很容易,因為:
它包含 Python 直譯器,因此您無需預先安裝它。還有一個在所有作業系統上執行的原始碼版本。
以下連結包含web2py的二進位制包,供使用者根據需要下載:www.web2py.com
與其他框架不同,web2py框架無需預先安裝。使用者需要下載 zip 檔案並根據作業系統要求解壓縮。
web2py框架是用 Python 編寫的,Python 是一種完整的動態語言,無需任何編譯或複雜的安裝即可執行。
它使用虛擬機器,就像其他程式語言(如 Java 或 .net)一樣,它可以透明地位元組編譯開發人員編寫的原始碼。
| 作業系統 | 命令 |
|---|---|
| Unix 和 Linux(原始碼分發版) | python web2py.py |
| OS X(二進位制分發版) | open web2py.app |
| Windows(二進位制 web2py 分發版) | web2py.exe |
| Windows(原始碼 web2py 分發版) | c:/Python27/python.exe web2py.py |
Web2py - Python 語言
Python 可以定義為面向物件和互動式語言的組合。它是一個開源軟體。Guido van Rossum 在 20 世紀 80 年代後期構思了 Python。
Python 是一種類似於 PERL(實用提取和報告語言)的語言,由於其清晰的語法和可讀性而廣受歡迎。
Python 的主要顯著特點如下:
據說 Python 相對容易學習且可移植。它的語句可以很容易地在許多作業系統中解釋,包括基於 UNIX 的系統、Mac OS、MS-DOS、OS/2和各種版本的 Windows。
Python 可移植到所有主要作業系統。它使用易於理解的語法,使程式對使用者友好。
它附帶一個大型標準庫,支援許多工。
從上圖可以清楚地看出,Python 是指令碼語言和程式語言的組合。它們在另一個程式中解釋,就像指令碼語言一樣。
Python 版本
Python 有三個生產質量的實現,稱為 CPython、Jython 和 IronPython。這些也被稱為 Python 版本。
經典 Python 又名 CPython 是一個編譯器、直譯器,包含用標準 C 語言實現的內建和可選擴充套件模組。
Jython 是針對 Java 虛擬機器 (JVM) 的 Python 實現。
IronPython 由微軟設計,包含公共語言執行時 (CLR)。它通常被稱為 .NET。
啟動
任何作業系統中的基本 Python 程式都以標題開頭。程式以.py副檔名儲存,並使用 Python 命令執行程式。
例如,python_rstprogram.py將為您提供所需的輸出。如果存在錯誤,它也會生成錯誤。
Python 使用縮排分隔程式碼塊。一個塊以以冒號結尾的行開頭,並繼續以與下一行相同或更高的縮排方式對所有行執行。
# Basic program in Python print "Welcome to Python!\n"
程式的輸出將是:
Welcome to Python!
縮排
程式的縮排在 Python 中非常重要。對於 Python 初學者來說,關於 Python 的縮排規則存在一些偏見和神話。
所有程式設計師的經驗法則:
“在 Python 原始碼中,空格很重要。”
前導空格,包括 Python 程式碼行開頭的空格和製表符,計算該行的縮排級別。
注意
縮排級別也決定了語句的分組。
通常使用四個空格,即每個縮排級別使用一個製表符。
最好不要混合使用製表符和空格,這可能會導致混亂,而這種混亂是不可見的。
如果缺少縮排,Python 也會生成編譯時錯誤。
IndentationError: expected an indented block
控制流語句
Python 程式的控制流受條件語句、迴圈和函式呼叫的控制。
If 語句在指定條件下執行程式碼塊,以及 else 和 elif(else-if 的組合)。
For 語句迭代物件,將每個元素捕獲到區域性變數中,供附加的程式碼塊使用。
While 語句在條件為True時執行程式碼塊。
With 語句將程式碼塊包含在上下文管理器中。它作為try/finally語句的可讀性更高的替代方案被新增。
# If statement in Python
x = int(raw_input("Please enter an integer: ")) #Taking input from the user
if x<0:
print "1 - Got a negative expression value"
print x
else:
print "1 - Got a positive expression value"
print x
print "Good bye!"
輸出
sh-4.3$ python main.py Please enter an integer: 4 1 - Got a positive expression value 4 Good bye!
函式
典型 Python 程式中的語句以特定格式組織和分組,稱為“函式”。函式是一組語句,根據請求執行操作。Python 提供了許多內建函式,並允許程式設計師定義自己的函式。
在 Python 中,函式是像程式語言中的其他物件一樣處理的值。
def語句是定義函式最常見的方式。def是一個單子句複合語句,具有以下語法:
def function-name (parameters):statement(s)
以下示例演示了一個生成器函式。它可以用作可迭代物件,以類似的方式建立其物件。
def demo ():
for i in range(5):
yield (i*i)
for j in demo():
print j
輸出
sh-4.3$ python main.py 0 1 4 9 16
特殊屬性、方法和運算子
類中以雙下劃線開頭的屬性、方法和運算子通常在行為上是私有的。其中一些是保留關鍵字,具有特殊含義。
其中三個列出如下:
__len__
__getitem__
__setitem__
其他特殊運算子包括 __getattr__ 和 __setattr__,它們定義了類的get和set屬性。
檔案 I/O 函式
Python 包括開啟和關閉特定檔案的功能。這可以透過open()、write()和close()函式來實現。
以下是一些用於檔案輸入輸出的命令:
| 序號 | 命令及功能 |
|---|---|
| 1 |
open() 用於開啟檔案或文件 |
| 2 |
write() 用於向檔案或文件中寫入字串 |
| 3 |
read() 用於讀取現有檔案中的內容 |
| 4 |
close() 此方法關閉檔案物件。 |
示例
假設有一個名為“demo.txt”的檔案,其中已經存在文字“This is a demo file”。
#!/usr/bin/python
# Open a file
fo = open("demo.txt", "wb")
fo.write( "Insering new line \n");
# Close opend file
fo.close()
開啟檔案後可用的字串將為:
This is a demo file Inserting a new line
Web2py - 框架概述
web2py是一個全棧Web框架,開發人員可以使用它來完整地開發Web應用程式。它包括SQL資料庫整合和多執行緒Web伺服器,用於設計程式。
用於設計使用者程式的Web介面
根據作業系統執行命令後,web2py會顯示一個啟動視窗,然後顯示一個GUI小部件,提示使用者選擇:
- 一次性管理員密碼,
- 要用於Web伺服器的網路介面的IP地址,
- 以及用於提供請求的埠號。
管理員擁有新增和編輯任何新Web應用程式的所有許可權。
預設情況下,web2py在其Web伺服器上執行127.0.0.1:8000(本地主機上的8000埠),但使用者可以根據需要在任何可用的IP地址和埠上執行它。
web2py GUI小部件將顯示如下。
密碼用於在管理介面中對新模組進行任何更改。
使用者設定管理員密碼後,web2py將在以下URL的頁面上啟動Web瀏覽器:http://127.0.0.1:8000/
框架的歡迎頁面將顯示如下。
在web2py中設計基本程式
啟動web2py應用程式後,使用上述URL,我們可以使用管理介面建立新的模組,例如“helloWorld”。
管理介面將要求輸入密碼以進行身份驗證,因為管理員擁有新增和編輯任何新Web應用程式的所有許可權。
上面給出的快照包含頁面詳細資訊,其中列出了所有已安裝的web2py應用程式,並允許管理員管理它們。預設情況下,web2py框架帶有三個應用程式。它們是:
使用者當前正在實現的admin應用程式。
一個examples應用程式,其中包含線上互動式文件和web2py官方網站的例項。
一個welcome應用程式。它包含任何其他web2py應用程式的基本模板。它也被稱為腳手架應用程式。該應用程式還在啟動時歡迎使用者。
假設新應用程式的名稱為“helloWorld”。
建立新應用程式後,使用者將被重定向到一個包含相應應用程式的檢視、模型和控制器的頁面。
使用者可以透過提及以下URL檢視新建立的應用程式:http://127.0.0.1:8000/helloWorld
預設情況下,使用者在點選上述URL時可以看到以下螢幕。
要列印給定Web應用程式“helloWorld”的訊息,需要在default.py控制器中進行更改。
名為“index”的函式是用於返回值並顯示必要輸出的預設函式。如上所述,字串“Hello World- Welcome to my first web application”用作返回值,它在螢幕上顯示輸出。
輸出顯示如下:
回發
驗證表單輸入的機制非常常見,並且不被認為是一種良好的程式設計實踐。每次都會驗證輸入,這對驗證來說是一種負擔。
web2py中更好的模式是將表單提交到生成它們的相同操作。這種機制稱為“回發”,它是web2py的主要功能。簡而言之,在回發中實現了自我提交。
def first():
if request.vars.visitor_name: #if visitor name exists
session.visitor_name = request.vars.visitor_name
redirect(URL('second'))#postback is implemented
return dict()
CRUD應用程式
web2py包括執行建立、檢索、更新和刪除功能的應用程式。CRUD迴圈描述了永續性資料庫的基本功能。
所有應用程式邏輯都寫在模型中,這些模型由控制器檢索,並藉助檢視顯示給使用者。
appadmin
對於PHP,應用程式伺服器包括在phpmyadmin下列出所有資料庫。類似地,web2py提供了一個用於管理、建立和刪除表或資料庫的介面,稱為“appadmin”。
在實現表背後的邏輯之前,有必要建立資料庫及其關聯的表。
訪問appadmin的URL:
http://127.0.0.1:8000/applicationname/appadmin
點選URL後,使用者將獲得與給定應用程式關聯的表的列表。
此介面並非旨在公開使用。它旨在輕鬆訪問資料庫。它包含兩個檔案,即控制器“appadmin.py”和檢視“appadmin.html”。
它可以一次最多分頁100條記錄。“appadmin”的使用將在後續章節中討論。
Web2py - 核心
命令列選項
在上一章中,我們學習瞭如何使用GUI小部件啟動web2py伺服器。
可以透過從命令列提示符啟動伺服器來跳過此小部件。
python web2py.py -a 'your password' -i 127.0.0.1 -p 8000
每當web2py伺服器啟動時,它都會建立一個檔案“parameters_8000.py”,其中所有密碼都以雜湊形式儲存。
出於額外的安全目的,可以使用以下命令列:
python web2py.py -a '<recycle>' -i 127.0.0.1 -p 8000
對於上述場景,web2py會重用儲存在“parameters_8000.py”中的雜湊密碼。
如果意外刪除或由於其他原因刪除了檔案“parameters_8000.py”,則web2py中的基於Web的管理介面將被停用。
URL對映/排程
web2py的功能基於模型-檢視-控制器,它以特定形式對映URL:http://127.0.0.1:8000/a/d/f.html
它路由到名為“a”的應用程式下控制器d.py中提到的函式“f()”。如果應用程式中不存在控制器,則web2py使用名為“default.py”的預設控制器。
如果URL中給定的函式不存在,則使用名為init()的預設函式。URL的工作原理如下圖所示。
副檔名.html對於URL是可選的。副檔名確定呈現控制器中定義的函式輸出的檢視的副檔名。相同的內容以多種格式提供,例如html、xml、json、rss等。
請求基於接受引數並向用戶提供適當輸出的函式傳遞。它是控制器,它與應用程式的模型和檢視互動,以根據使用者的需要提供輸出。
web2py – 工作流程
web2py的工作流程如下:
Web伺服器在其自己的執行緒中同時管理每個HTTP請求。
HTTP請求標頭被解析並傳遞給排程程式。
排程程式管理應用程式請求並將URL中的PATH_INFO對映到函式呼叫。每個函式呼叫都表示在URL中。
直接管理靜態資料夾中包含的所有檔案的請求,並將大型檔案流式傳輸到客戶端。
除了靜態檔案之外的所有請求都對映到一個操作。
如果請求標頭包含應用程式的會話cookie,則檢索會話物件;否則,將建立會話ID。
如果操作返回字串值,則將其返回給客戶端。
如果操作返回可迭代物件,則將其用於迴圈並將資料流式傳輸到客戶端。
條件模型
在上一章中,我們看到了控制器的功能。web2py在其每個應用程式中都使用模型、檢視和控制器。因此,瞭解模型的功能也很有必要。
與任何其他MVC應用程式不同,web2py中的模型被視為條件模型。子資料夾中的模型根據其控制器的使用情況執行。這可以透過以下示例演示:
考慮URL:http://127.0.0.1:8000/a/d/f.html
在這種情況下,“a”是應用程式的名稱,“d”是控制器的名稱,f()是與控制器關聯的函式。將執行的模型列表如下:
applications/a/models/*.py applications/a/models/d/*.py applications/a/models/d/f/*.py
庫
web2py包括庫,這些庫作為物件公開給所有應用程式。這些物件在名為“gluon”的目錄下的核心檔案中定義。
許多模組(如DAL模板)沒有依賴項,可以在web2py框架之外實現。它還維護單元測試,這被認為是一種良好的實踐。
應用程式
web2py應用程式在下面的圖表中顯示。
在web2py中開發的應用程式由以下部分組成:
模型 - 表示資料和資料庫表。
控制器 - 描述應用程式邏輯和工作流程。
檢視 - 幫助呈現資料的顯示。
語言 - 描述如何將應用程式中的字串翻譯成各種支援的語言。
靜態檔案 - 不需要處理(例如影像、CSS樣式表等)。
ABOUT和README - 專案的詳細資訊。
錯誤 - 儲存應用程式生成的錯誤報告。
會話 - 儲存與每個特定使用者相關的資訊。
資料庫 - 儲存SQLite資料庫和其他表資訊。
快取 - 儲存快取的應用程式項。
模組 - 模組是其他可選的Python模組。
私有 - 包含的檔案可被控制器訪問,但開發人員不能直接訪問。
上傳 - 檔案可被模型訪問,但開發人員不能直接訪問。
API
在web2py中,模型、控制器和檢視在匯入某些物件的開發人員環境中執行。
全域性物件 - request、response、session、cache。
助手 - web2py包括助手類,可用於以程式設計方式構建HTML。它對應於HTML標籤,稱為“HTML助手”。
例如,A、B、FIELDSET、FORM等。
會話
會話可以定義為伺服器端資訊的儲存,這些資訊在使用者與整個Web應用程式互動的過程中持續存在。
web2py中的會話是儲存類的例項。
例如,可以在會話中儲存變數,如下所示
session.myvariable = "hello"
此值可以檢索如下
a = session.myvariable
只要同一使用者在同一會話中執行程式碼,就可以檢索變數的值。
web2py中用於會話的重要方法之一是“forget”:
session.forget(response);
它指示web2py不要儲存會話。
在後臺執行任務
HTTP請求到達Web伺服器,Web伺服器在其自己的執行緒中並行處理每個請求。正在進行的任務發生在前景中,而其他任務則保留在後臺。管理後臺任務也是web2py的主要功能之一。
耗時的任務最好放在後臺。一些管理後臺任務的機制列出如下:
CRON
佇列
排程程式
CRON
在web2py中,CRON能夠在指定的時間間隔內執行任務。每個應用程式都包含一個CRON檔案,該檔案定義其功能。
排程程式
內建排程程式透過設定優先順序幫助在後臺執行任務。它提供了一種建立、排程和修改任務的機制。
計劃的事件在模型中列出,檔名是“scheduler.py”。
構建應用程式
我們概述了在web2py中建立模型和控制器。在這裡,我們將重點關注名為“Contacts”的應用程式的建立。該應用程式需要維護公司列表和在這些公司工作的員工列表。
建立模型
此處,資料字典中表的標識是模型。聯絡人應用程式的模型將在“models”資料夾下建立。該檔案儲存在models/db_contacts.py中。
# in file: models/db_custom.py
db.define_table('company', Field('name', notnull = True, unique = True), format = '%(name)s')
db.define_table(
'contact',
Field('name', notnull = True),
Field('company', 'reference company'),
Field('picture', 'upload'),
Field('email', requires = IS_EMAIL()),
Field('phone_number', requires = IS_MATCH('[\d\-\(\) ]+')),
Field('address'),
format = '%(name)s'
)
db.define_table(
'log',
Field('body', 'text', notnull = True),
Field('posted_on', 'datetime'),
Field('contact', 'reference contact')
)
建立上述檔案後,可以透過URL http://127.0.0.1:8000/contacts/appadmin訪問這些表。
控制器建立
控制器將包含一些用於列出、編輯和刪除聯絡人的函式。
# in file: controllers/default.py
def index():return locals()
def companies():companies = db(db.company).select(orderby = db.company.name)
return locals()
def contacts():company = db.company(request.args(0)) or redirect(URL('companies'))
contacts = db(db.contact.company == company.id).select(orderby = db.contact.name)
return locals()
@auth.requires_login()
def company_create():form = crud.create(db.company, next = 'companies')
return locals()
@auth.requires_login()
def company_edit():company = db.company(request.args(0)) or redirect(URL('companies'))
form = crud.update(db.company, company, next='companies')
return locals()
@auth.requires_login()
def contact_create():db.contact.company.default = request.args(0)
form = crud.create(db.contact, next = 'companies')
return locals()
@auth.requires_login()
def contact_edit():contact = db.contact(request.args(0)) or redirect(URL('companies'))
form = crud.update(db.contact, contact, next = 'companies')
return locals()
def user():return dict(form = auth())
檢視的建立及其輸出將在下一章中討論。
Web2py - 檢視
web2py框架在其應用程式中使用模型、控制器和檢視。它在檢視中包含了略微修改的Python語法,以便在不限制正確使用Python的情況下獲得更易讀的程式碼。
web2py檢視的主要目的是將python程式碼嵌入到HTML文件中。但是,它面臨一些問題,如下所示:
- 在HTML文件中轉義嵌入的python程式碼。
- 遵循基於Python的縮排,這可能會影響HTML規則。
為了解決這些問題,web2py在檢視部分使用分隔符{{..}}。這些分隔符有助於轉義嵌入的python程式碼。它還有助於遵循HTML的縮排規則。
包含在{{..}}分隔符內的程式碼包含意外的Python程式碼。由於Python通常使用縮排分隔程式碼塊,因此分隔符內的意外程式碼應以正確的方式維護。為了克服這個問題,web2py使用“pass”關鍵字。
以行開頭並以冒號結尾的程式碼塊以以pass開頭的行結束。
注意 - pass是Python關鍵字,它不是web2py關鍵字。
以下程式碼顯示了pass關鍵字的實現:
{{
if num > 0:
response.write('positive number')
else:
response.write('negative number')
pass
}}
HTML助手
web2py包含助手類,可用於以程式設計方式構建HTML程式。它對應於HTML標籤,稱為“HTML助手”。
例如:
[(A('Home', _href = URL('default', 'home')), False, None, []), ...]
這裡,A是對應於HTML錨<a>標籤的助手。它以程式設計方式構建HTML錨<a>標籤。
HTML助手由兩種型別組成,即位置和命名引數。
位置引數被解釋為包含在HTML開始和結束標籤之間的物件。
以下劃線開頭的命名引數被解釋為HTML標籤。
助手在字串序列化中也很有用,使用_str_和xml方法。例如:
>>> print str(DIV(“hello world”))
輸出
<div> hello world </div>
注意 - HTML助手提供了文件物件模型(DOM)的伺服器端表示。
XML助手
XML被稱為一個物件,它封裝了不應該轉義的文字。文字可能包含也可能不包含有效的XML。
例如,對於下面提到的程式碼,它可能包含JavaScript。
>>> print XML('<script>alert("unsafe!")</script>')
輸出
<script> alert(“unsafe!”)</script>
內建助手
web2py中使用了許多內建助手。一些HTML內建助手如下所示。
| 名稱 | 用法 | 示例 |
|---|---|---|
| A | 此助手用於構建連結。它對應於錨標籤 |
[
(A('Home', _href = URL('default', 'home')), False, None, []),
...]
|
| B | 此助手有助於使文字內容加粗。 |
B('<hello>', XML('<i>world</i>'), _class = 'test', _id = 0)
|
| BODY | 此助手建立頁面的主體。它還包含一個乘法運算子以增加換行符的數量。 |
BR() |
| CODE | 它對Python、C、C++和web2py程式碼執行語法高亮顯示。此助手還可以連結API文件。 |
CODE('print "hello"', language = 'python').xml()
|
| FIELDSET | 它建立輸入欄位及其標籤。 |
FIELDSET('Height:', INPUT(_name = 'height'), _class = 'test')
|
| HEAD | 它有助於標記HTML頁面的<head>標籤。 |
HEAD(TITLE('<hello>'))
|
| IMG | 它有助於為給定的HTML頁面嵌入影像。 |
IMG(_src = 'http://example.com/image.png',_alt = 'test') |
自定義助手
這些助手用於根據需要自定義標籤。web2py使用以下自定義助手:
TAG
web2py使用TAG作為通用標籤生成器。它有助於生成自定義XML標籤。通用語法如下:
{{ = TAG.name('a', 'b', _c = 'd')}}
它生成以下XML程式碼:<name c = "d">ab</name>
TAG是一個物件,而TAG.name或TAG['name']是一個返回臨時助手類的函式。
MENU
此助手列出列表項或選單項的值,生成一個樹狀結構來表示選單。選單項列表的形式為response.menu。例如:
print MENU([['One', False, 'link1'], ['Two', False, 'link2']])
輸出將顯示如下:
<ul class = "web2py-menu web2py-menu-vertical"> <li><a href = "link1">One</a></li> <li><a href = "link2">Two</a></li> </ul>
BEAUTIFY
它有助於構建複合物件的表示形式,包括列表和字典。例如,
{{ = BEAUTIFY({"a": ["hello", XML("world")], "b": (1, 2)})}}
它返回一個可序列化為XML的XML物件,幷包含其建構函式引數的表示形式。在這種情況下,表示形式將是:
{"a": ["hello", XML("world")], "b": (1, 2)}
輸出將呈現為:
<table>
<tr>
<td>a</td>
<td>:</td>
<td>hello<br />world</td>
</tr>
<tr>
<td>b</td>
<td>:</td>
<td>1<br />2</td>
</tr>
</table>
伺服器端DOM渲染
伺服器端渲染允許使用者預渲染web2py元件的初始狀態。所有派生的助手都提供搜尋元素和元素以在伺服器端渲染DOM。
element返回與指定條件匹配的第一個子元素。另一方面,elements返回所有匹配子元素的列表。兩者使用相同的語法。
這可以透過以下示例演示:
a = DIV(DIV(DIV('a', _id = 'target',_class = 'abc')))
d = a.elements('div#target')
d[0][0] = 'changed'
print a
輸出如下:
<div><div><div id = "target" class = "abc">changed</div></div></div>
頁面佈局
檢視用於將輸出顯示給終端使用者。它可以擴充套件也可以包含其他檢視。這將實現一個樹狀結構。
例如 - “index.html”擴充套件到“layout.html”,它可以包含“menu.html”,而“menu.html”又包含“header.html”。
{{extend 'layout.html'}}
<h1>Hello World</h1>
{{include 'page.html'}}
示例
在前面的章節中,我們為公司模組建立了模型和控制器。現在,我們將重點關注檢視的建立,它有助於呈現資料的顯示。
預設情況下,web2py中的檢視包括layout.html和index.html,它們定義了顯示資料的整體部分。
{{extend 'layout.html'}}
<h2>Companies</h2>
<table>
{{for company in companies:}}
<tr>
<td>{{ = A(company.name, _href = URL('contacts', args = company.id))}}</td>
<td>{{ = A('edit', _href = URL('company_edit', args = company.id))}}</td>
</tr>
{{pass}}
<tr>
<td>{{ = A('add company', _href = URL('company_create'))}}</td>
</tr>
</table>
輸出將如下所示:
Web2py - 資料庫抽象層
資料庫抽象層(DAL)被認為是web2py的主要優勢。DAL向底層SQL語法公開了簡單的應用程式程式設計介面(API)。
在本章中,我們將瞭解DAL的一些非平凡應用,例如構建查詢以有效地按標籤搜尋以及構建分層類別樹。
DAL的一些重要特性包括:
web2py包含一個數據庫抽象層(DAL),這是一個將Python物件對映到資料庫物件的API。資料庫物件可以是查詢、表和記錄。
DAL使用為資料庫後端指定的方言即時動態生成SQL,因此開發人員不必編寫完整的SQL查詢。
使用DAL的主要優勢在於,應用程式可以與不同型別的資料庫移植。
DAL入門
web2py中的大多數應用程式都需要資料庫連線。因此,構建資料庫模型是應用程式設計的第一個步驟。
考慮名為“helloWorld”的新建立的應用程式。資料庫在應用程式的模型下實現。所有相應應用程式的模型都包含在名為models/db_custom.py的檔案中。
實現DAL使用以下步驟:
步驟1 - DAL建構函式
建立資料庫連線。這是使用DAL物件建立的,該物件也稱為DAL建構函式。
db = DAL ('sqlite://storage.sqlite')
DAL的一個顯著特點是它允許與同一個資料庫或不同的資料庫建立多個連線,甚至可以與不同型別的資料庫建立連線。可以觀察到,此行已存在於models/db.py檔案中。因此,您可能不需要它,除非您刪除了它或需要連線到不同的資料庫。預設情況下,web2py連線到儲存在storage.sqlite檔案中的SQLite資料庫。
此檔案位於應用程式的databases資料夾中。如果該檔案不存在,則在第一次執行應用程式時由web2py建立。
SQLite速度很快,並將所有資料儲存在一個檔案中。這意味著您的資料可以輕鬆地從一個應用程式傳輸到另一個應用程式。事實上,SQLite資料庫與應用程式一起打包在web2py中。它提供完整的SQL支援,包括翻譯、聯接和聚合。
SQLite有兩個缺點。
一個是它不強制執行列型別,並且除了新增和刪除列之外,沒有ALTER TABLE。
另一個缺點是,任何需要寫訪問許可權的事務都會鎖定整個資料庫。
步驟2 - 表建構函式
一旦與資料庫建立連線,我們就可以使用define_table方法來定義新表。
例如:
db.define_table('invoice',Field('name'))
上述方法也在表建構函式中使用。表建構函式的語法相同。第一個引數是表名,後面跟著一個欄位(Field)列表。欄位建構函式採用以下引數:
| 序號 | 引數和用法 |
|---|---|
| 1 |
欄位名稱 表中欄位的名稱。 |
| 2 |
欄位型別 採用具有任何資料型別的值,例如字串(預設)、文字、布林值、整數等。 |
| 3 |
長度 定義最大長度。 |
| 4 |
default = None 這是插入新記錄時的預設值。 |
| 5 |
update = None 此功能與default相同,但該值僅在更新時使用,而不是在插入時使用。 |
| 6 |
Notnull 這指定欄位值是否可以為NULL。 |
| 7 |
readable = True 這指定欄位是否在表單中可讀。 |
| 8 |
writable = True 這指定欄位是否在表單中可寫。 |
| 9 |
label = "Field Name" 這是在表單中用於此欄位的標籤。 |
define_table方法還採用三個命名引數:
語法
db.define_table('....',migrate=True, fake_migrate=False, format = '%(id)s')
migrate = True - 這指示web2py在表不存在時建立它,或者在它與模型定義不匹配時更改它。
fake_migrate = False - 如果模型與資料庫表內容匹配,則將fake_migrate設定為True,這有助於web2py重建資料。
format = '%(id)s' - 這是一個格式字串,用於確定如何表示給定表上的記錄。
生成原始SQL
使用DAL,我們可以建立與資料庫的連線,並使用表建構函式和欄位建構函式建立新表及其欄位。
有時,需要生成SQL語句以符合必要的輸出。web2py包含各種函式,這些函式有助於生成原始SQL,如下所示:
_insert
它有助於為給定表獲取插入語句。例如,
print db.person._insert(name ='ABC')
它將檢索名為“person”表的插入語句。
SQL語句輸出:
INSERT INTO person(name) VALUES ('ABC');
_count
它有助於獲取SQL語句,該語句給出記錄的數量。例如,考慮一個名為“person”的表,我們需要查詢姓名為“ABC”的人員數量。
print db(db.person.name ==' ABC ')._count()
SQL語句輸出:
SELECT count(*) FROM person WHERE person.name = ' ABC ';
_select
它有助於獲取select SQL語句。例如,考慮一個名為“person”的表,我們需要查詢姓名為“ABC”的人員列表。
print db(db.person.name == ' ABC ')._select()
SQL語句輸出:
SELECT person.name FROM person WHERE person.name = ' ABC ';
_delete
它有助於獲取delete SQL語句。例如,考慮名為“person”的表,我們需要刪除姓名為“ABC”的語句。
print db(db.person.name == ' ABC ')._delete()
SQL語句輸出:
DELETE FROM person WHERE person.name = ' ABC ';4
_update
它有助於獲取更新的SQL語句。例如,考慮名為“person”的表,我們需要將列名更新為其他值。
print db(db.person.name == ' ABC ')._update()
SQL語句輸出:
UPDATE person SET WHERE person.name = ’Alex’;
DAL問題(注意事項)
SQLite
SQLite缺乏刪除或更改列的支援。從表中刪除欄位會使其在資料庫中保持活動狀態,因此web2py將不會意識到所做的任何更改。
在這種情況下,有必要將fake_migrate = True設定為True,這將有助於重新定義元資料,以便任何更改(例如更改或刪除)都將在web2py的瞭解範圍內。
SQLite不支援布林型別。為此,web2py在內部將布林值對映到1個字元字串,其中'T'和'F'分別表示true和False。
MySQL
MySQL 不支援 ALTER TABLE 功能。因此,資料庫遷移涉及多個提交。可以透過在定義資料庫時設定引數fake_migrate = True來避免這種情況,這將保留所有元資料。
Oracle
Oracle 不支援記錄分頁功能。它也不支援 OFFSET 或 limit 關鍵字。為此,web2py 透過使用複雜的 DAL 三重巢狀選擇來實現分頁。如果使用了 Oracle 資料庫,DAL 需要自行處理分頁。
Web2py - 表單 & 驗證器
web2py 帶有強大的表單生成功能。在 web2py 中構建表單的四種不同方法如下:
FORM - 就 HTML 助手而言,它被認為是低階實現。FORM 物件知道其欄位內容。
SQLFORM - 它為現有資料庫提供建立、更新和刪除的功能。
SQLFORM.factory - 它被認為是 SQLFORM 之上的抽象層,它生成類似於 SQLFORM 的表單。這裡不需要建立新的資料庫。
CRUD 方法 - 顧名思義,它提供了基於 SQLFORM 的具有類似功能的建立、檢索、更新和刪除功能。
FORM
考慮一個應用程式,它接受使用者的輸入並有一個“提交”按鈕來提交響應。
控制器
“default.py”控制器將包含以下關聯函式
def display_form(): return dict()
檢視
關聯檢視“default/display_form.html”將以 HTML 渲染表單的顯示如下:
{{extend 'layout.html'}}
<h2>Basic Form</h2>
<form enctype = "multipart/form-data" action = "{{= URL()}}" method = "post">
Your name:
<input name = "name" />
<input type = "submit" />
</form>
<h2>Submitted variables</h2>
{{= BEAUTIFY(request.vars)}}
以上示例是普通的 HTML 表單,它請求使用者輸入。可以使用 FORM 物件等助手生成相同的表單。
控制器
def display_form():
form = FORM('Value:', INPUT(_value = 'name'), INPUT(_type = 'submit'))
return dict(form = form)
“default.py”控制器中的上述函式包含 FORM 物件(HTML 助手),它有助於建立表單。
檢視
{{extend 'layout.html'}}
<h2>Basic form</h2>
{{= form}}
<h2>Submitted variables</h2>
{{= BEAUTIFY(request.vars)}}
語句{{= form}}生成的表單序列化 FORM 物件。當用戶填寫表單並點選提交按鈕時,表單會自行提交,並且變數request.vars.value及其輸入值會顯示在底部。
SQLFORM
它有助於為現有資料庫建立表單。下面討論了其實現步驟。
使用 DAL 建立與資料庫的連線,這是使用 DAL 物件建立的,也稱為 DAL 建構函式。建立連線後,使用者可以建立相應的表。
db = DAL('sqlite://storage.sqlite')
db.define_table('employee', Field('name', requires = IS_NOT_EMPTY()))
因此,我們建立了一個名為“employee”的表。控制器使用以下語句構建表單和按鈕:
form = SQLFORM(
db.mytable,
record = mytable_index,
deletable = True,
submit_button = T('Update')
)
因此,對於建立的 employee 表,控制器中的修改將是:
def display_form(): form = SQLFORM(db.person)
檢視中沒有修改。在新控制器中,需要構建一個 FORM,因為在模型中定義的 SQLFORM 建構函式從表 db.employee 構建了一個。新表單序列化後,顯示如下:
<form enctype = "multipart/form-data" action = "" method = "post">
<table>
<tr id = "employee_name__row">
<td>
<label id = "person_name__label" for = "person_name">Your name: </label>
</td>
<td>
<input type = "text" class = "string" name = "name" value = "" id = "employee_name" />
</td>
<td></td>
</tr>
<tr id = "submit_record__row">
<td></td>
<td><input value = "Submit" type = "submit" /></td>
<td></td>
</tr>
</table>
<input value = "9038845529" type = "hidden" name = "_formkey" />
<input value = "employee" type = "hidden" name = "_formname" />
</form>
表單中的所有標籤都具有從表和欄位名稱派生的名稱。
SQLFORM 物件還可以處理“上傳”欄位,方法是將上傳的檔案儲存在“uploads”資料夾中。這是自動完成的。SQLFORM 使用複選框顯示“布林”值,並使用“textareas”顯示文字值。
SQLFORM 還使用 process 方法。如果使用者希望保留與關聯的 SQLFORM 關聯的值,則需要這樣做。
如果form.process(keepvalues = True),則接受。
示例
def display_form(): form = SQLFORM(db.employee) if form.process().accepted: response.flash = 'form accepted' elif form.errors: response.flash = 'form has errors' else: response.flash = 'please fill out the form' return dict(form = form)
SQLFORM.factory
有時,使用者需要以一種方式生成表單,即存在一個現有資料庫表,但沒有實現資料庫。使用者只是想利用 SQLFORM 的功能。
這是透過form.factory完成的,它儲存在會話中。
def form_from_factory():
form = SQLFORM.factory(
Field('your_name', requires = IS_NOT_EMPTY()),
Field('your_image', 'upload'))
if form.process().accepted:
response.flash = 'form accepted'
session.your_name = form.vars.your_name
session.your_image = form.vars.your_image
elif form.errors:
response.flash = 'form has errors'
return dict(form = form)
該表單將顯示為 SQLFORM,其欄位為名稱和影像,但資料庫中不存在這樣的表。
“default/form_from_factory.html”檢視將表示為:
{{extend 'layout.html'}}
{{= form}}
CRUD 方法
CRUD 是在 SQLFORM 之上使用的 API。顧名思義,它用於建立、檢索、更新和刪除相應的表單。
與 web2py 中的其他 API 相比,CRUD 未公開;因此,必須匯入它。
from gluon.tools import Crud crud = Crud(db)
上面定義的 CRUD 物件提供了以下 API:
| 序號 | API & 功能 |
|---|---|
| 1 |
crud.tables() 返回資料庫中定義的表列表。 |
| 2 |
crud.create(db.tablename) 返回表 tablename的建立表單。 |
| 3 |
crud.read(db.tablename, id) 返回tablename和記錄 id 的只讀表單。 |
| 4 |
crud.delete(db.tablename, id) 刪除記錄 |
| 5 |
crud.select(db.tablename, query) 返回從表中選擇的記錄列表。 |
| 6 |
crud.search(db.tablename) 返回一個元組 (form, records),其中 form 是搜尋表單。 |
| 7 |
crud() 根據 request.args() 返回上述內容之一。 |
表單建立
讓我們建立一個表單。請按照以下程式碼操作。
模型
在應用程式的models資料夾下建立一個新的模型。檔名為“dynamic_search.py”。
def build_query(field, op, value):
if op == 'equals':
return field == value
elif op == 'not equal':
return field != value
elif op == 'greater than':
return field > value
elif op == 'less than':
return field < value
elif op == 'starts with':
return field.startswith(value)
elif op == 'ends with':
return field.endswith(value)
elif op == 'contains':
return field.contains(value)
def dynamic_search(table):
tbl = TABLE()
selected = []
ops = ['equals',
'not equal',
'greater than',
'less than',
'starts with',
'ends with',
'contains']
query = table.id > 0
for field in table.fields:
chkval = request.vars.get('chk'+field,None)
txtval = request.vars.get('txt'+field,None)
opval = request.vars.get('op'+field,None)
row = TR(TD(INPUT(_type = "checkbox",_name = "chk"+field,value = chkval == 'on')),
TD(field),TD(SELECT(ops,_name = "op"+field,value = opval)),
TD(INPUT(_type = "text",_name = "txt"+field,_value = txtval)))
tbl.append(row)
if chkval:
if txtval:
query &= build_query(table[field], opval,txtval)
selected.append(table[field])
form = FORM(tbl,INPUT(_type="submit"))
results = db(query).select(*selected)
return form, results
控制器
控制器部分名為“dynamic_search.py”的關聯檔案將包含以下程式碼:
def index(): form,results = dynamic_search(db.things) return dict(form = form,results = results)
檢視
我們可以使用以下檢視呈現它。
{{extend 'layout.html'}}
{{= form}}
{{= results}}
它看起來像這樣:
Web2py - 郵件 & 簡訊
web2py 包括向用戶傳送電子郵件和簡訊的功能。它使用庫來發送電子郵件和簡訊。
設定電子郵件
名為gluon.tools.Mail的內建類用於在 web2py 框架中傳送電子郵件。郵件伺服器可以使用此類定義。
from gluon.tools import Mail mail = Mail() mail.settings.server = 'smtp.example.com:25' mail.settings.sender = 'abc@example.com' mail.settings.login = 'username:password'
每次傳送電子郵件時,都會對上述示例中提到的發件人電子郵件及其密碼進行身份驗證。
如果使用者需要進行實驗或用於某些除錯目的,可以使用以下程式碼實現。
mail.settings.server = 'logging'
現在,所有電子郵件都不會發送,但會記錄在控制檯中。
傳送電子郵件
一旦我們使用郵件物件設定了電子郵件的配置設定,就可以向許多使用者傳送電子郵件。
mail.send()的完整語法如下:
send(
to, subject = 'Abc',
message = 'None', attachments = [],
cc = [], bcc = [], reply_to = [],
sender = None, encoding = 'utf-8',
raw = True, headers = {}
)
mail.send()的實現如下所示。
mail.send( to = ['sender@example.com'], subject = 'hello', reply_to = 'abc@example.com', message = 'Hello ! How are you?' )
Mail根據郵件伺服器的響應返回一個布林表示式,即終端使用者是否收到郵件。如果成功向用戶傳送電子郵件,則返回True。
屬性 to、cc和bcc包含要傳送郵件的有效電子郵件地址列表。
傳送簡訊
在 web2py 框架中,傳送簡訊的實現與傳送電子郵件不同,因為它需要第三方服務來將訊息轉發給接收者。第三方服務不是免費服務,並且顯然會因地理區域(從國家到國家)而異。
web2py 使用一個模組來幫助傳送簡訊,過程如下:
from gluon.contrib.sms_utils
import SMSCODES, sms_email
email = sms_email('1 (111) 111-1111','T-Mobile USA (abc)')
mail.send(to = email, subject = 'test', message = 'test')
在以上示例中,SMSCODES是 web2py 維持的字典,它將主要電話公司的名稱對映到電子郵件地址字尾。
電話公司通常將來自第三方服務的電子郵件視為垃圾郵件。更好的方法是電話公司自己轉發簡訊。每個電話公司在其儲存中為每個手機號碼包含一個唯一的電子郵件地址,並且可以將簡訊直接傳送到該電子郵件。
在以上示例中,
sms_email函式接收一個電話號碼(作為字串),返回該電話的電子郵件地址。
腳手架應用程式包含多個檔案。其中一個是 models/db.py,它匯入了四個。
來自gluon.tools的類也包括郵件庫,並定義了各種全域性物件。
腳手架應用程式還定義了 auth 物件所需的表,例如db.auth_user。預設腳手架應用程式旨在最大程度地減少檔案數量,而不是模組化。特別是模型檔案db.py包含配置,在生產環境中,最好將其儲存在單獨的檔案中。
在這裡,我們建議建立一個配置檔案:
from gluon.storage import Storage
settings = Storage()
settings.production = False
if
settings.production:
settings.db_uri = 'sqlite://production.sqlite'
settings.migrate = False
else:
settings.db_uri = 'sqlite://development.sqlite'
settings.migrate = True
settings.title = request.
settings.subtitle = 'write something here'
settings.author = 'you'
settings.author_email = 'you@example.come'
settings.keywords = ''
settings.description = ''
settings.layout_theme = 'Default'
settings.security_key = 'a098c897-724b-4e05-b2d8-8ee993385ae6'
settings.email_server = 'localhost'
settings.email_sender = 'you@example.com'
settings.email_login = ''
settings.login_method = 'local'
settings.login_config = ''
Web2py - 訪問控制
身份驗證
幾乎每個應用程式都需要能夠對使用者進行身份驗證並設定許可權。web2py 帶有一個廣泛且可定製的基於角色的訪問控制機制.web2py。它還支援 CAS、OpenID、OAuth 1.0、LDAP、PAM、X509 等協議。
web2py 包含一種稱為基於角色的訪問控制機制 (RBAC) 的機制,這是一種限制授權使用者訪問系統的方法。實現 RBAC 的 web2py 類稱為 Auth。
檢視下面的模式。
Auth定義了以下表:
| 序號 | 表名 & 描述 |
|---|---|
| 1 | auth_user 儲存使用者的姓名、電子郵件地址、密碼和狀態。 |
| 2 | auth_group 以多對多的結構儲存使用者的組或角色 |
| 3 | auth_membership 以多對多的結構儲存使用者和組連結的資訊 |
| 4 | auth_permission 該錶鏈接組和許可權。 |
| 5 | auth_event 記錄其他表中的更改和成功訪問 |
| 6 | auth_cas 它用於中央身份驗證服務 |
自定義 Auth
有兩種方法可以自定義 Auth。
從頭開始定義自定義db.auth_user表。
讓 web2py 定義auth表。
讓我們看看定義auth表的最後一種方法。在db.py模型中,替換以下行:
auth.define_tables()
將其替換為以下程式碼:
auth.settings.extra_fields['auth_user'] = [
Field('phone_number',requires = IS_MATCH('\d{3}\-\d{3}\-\d{4}')),
Field('address','text')
]
auth.define_tables(username = True)
假設每個使用者都包含電話號碼、使用者名稱和地址。
auth.settings.extra_fields是額外欄位的字典。鍵是要向其新增額外欄位的 auth 表的名稱。值是額外欄位的列表。在這裡,我們添加了兩個額外欄位,phone_number 和 address。
username必須以特殊方式處理,因為它涉及身份驗證過程,該過程通常基於電子郵件欄位。透過將 username 引數傳遞給以下行,它會通知 web2py 我們想要 username 欄位,並且我們希望使用它來登入而不是電子郵件欄位。它充當主鍵。
auth.define_tables(username = True)
使用者名稱被視為唯一值。在某些情況下,註冊可能發生在正常的登錄檔單之外。這種情況也可能發生,新使用者被迫登入以完成註冊。
這可以透過一個虛擬欄位complete_registration來完成,該欄位預設設定為False,並在他們更新個人資料時設定為True。
auth.settings.extra_fields['auth_user'] = [
Field('phone_number',requires = IS_MATCH('\d{3}\-\d{3}\-\d{4}'),
comment = "i.e. 123-123-1234"),
Field('address','text'),
Field('complete_registration',default = False,update = True,
writable = False, readable = False)
]
auth.define_tables(username = True)
這種情況可能意在讓新使用者在登入後完成註冊。
在db.py(models 資料夾中),我們可以追加以下程式碼:
if auth.user and not auth.user.complete_registration:
if not (request.controller,request.function) == ('default','user'):
redirect(URL('default','user/profile'))
這將強制新使用者根據需要編輯其個人資料。
授權
它是授予某些訪問許可權或向用戶授予某些許可權的過程。
在 web2py 中,一旦建立或註冊了新使用者,就會建立一個新組來包含該使用者。新使用者的角色通常稱為“user_[id]”,其中 id 是使用者的唯一標識。
建立新組的預設值為:
auth.settings.create_user_groups = "user_%(id)s"
可以透過以下方式停用使用者之間組的建立:
auth.settings.create_user_groups = None
建立、授予特定成員的訪問許可權和許可權可以透過 appadmin 的幫助以程式設計方式實現。
一些實現列出如下:
| 序號 | 命令 & 用法 |
|---|---|
| 1 | auth.add_group('role', 'description') 返回新建立組的 id。 |
| 2 | auth.del_group(group_id) 刪除具有指定 id 的組 |
| 3 | auth.del_group(auth.id_group('user_7')) 刪除具有給定標識的使用者組。 |
| 4 | auth.user_group(user_id) 返回與給定使用者唯一關聯的組 id 的值。 |
| 5 | auth.add_membership(group_id, user_id) 返回給定 group_id 的 user_id 值 |
| 6 | auth.del_membership(group_id, user_id) 撤銷給定 member_id(即 user_id)對給定組的訪問許可權。 |
| 7 | auth.has_membership(group_id, user_id, role) 檢查使用者ID是否屬於給定組。 |
中央認證服務 (CAS)
web2py 提供了一個行業標準,即客戶端認證服務 - CAS,用於 web2py 中的客戶端和伺服器內建功能。它是一個第三方身份驗證工具。
它是一個用於分散式身份驗證的開放協議。CAS 的工作原理如下:
如果使用者訪問網站,該協議會檢查使用者是否已透過身份驗證。
如果使用者未透過應用程式的身份驗證,則協議會重定向到使用者可以在其中註冊或登入應用程式的頁面。
如果註冊完成,使用者會收到一封電子郵件。除非使用者驗證電子郵件,否則註冊不完整。
註冊成功後,使用者將使用 CAS 裝置使用的金鑰進行身份驗證。
該金鑰用於透過 HTTP 請求獲取使用者憑據,該請求在後臺設定。
Web2py - 服務
web2py 支援各種協議,如 XML、JSON、RSS、CSV、XMLRPC、JSONRPC、AMFRPC 和 SOAP。每種協議都以多種方式支援,我們區分以下兩種情況:
- 以給定格式呈現函式的輸出。
- 遠端過程呼叫。
呈現字典
考慮以下維護會話計數的程式碼。
def count(): session.counter = (session.counter or 0) + 1 return dict(counter = session.counter, now = request.now)
上述函式在使用者訪問頁面時增加計數。假設給定函式在 web2py 應用程式的“default.py”控制器中定義。可以使用以下 URL 請求該頁面:http://127.0.0.1:8000/app/default/count
web2py 可以透過向 URL 新增副檔名,以不同的協議呈現上述頁面,例如:
http://127.0.0.1:8000/app/default/count.html
http://127.0.0.1:8000/app/default/count.xml
http://127.0.0.1:8000/app/default/count.json
上述操作返回的字典將以 HTML、XML 和 JSON 格式呈現。
遠端過程呼叫
web2py 框架提供了一種機制,可以將函式轉換為 Web 服務。此處描述的機制與之前描述的機制不同,因為:
- 在函式中包含引數。
- 函式必須在模型中定義。
- 它強制執行更嚴格的 URL 命名約定。
- 它適用於一組固定的協議,並且易於擴充套件。
- 要使用此功能,需要匯入並初始化服務物件。
要實現此機制,首先必須匯入並例項化服務物件。
from gluon.tools import Service service = Service()
這在腳手架應用程式的“db.py”模型檔案中實現。“Db.py”模型是 web2py 框架中的預設模型,它與資料庫和控制器互動,以向用戶提供所需的輸出。
實現後,可以根據需要從控制器訪問模型中的服務。
以下示例顯示了使用 Web 服務實現遠端過程呼叫的各種方法,以及更多方法。
Web 服務
Web 服務可以定義為使用 XML、SOAP、WSDL 和 UDDI 等協議整合基於 Web 的應用程式的標準化方法。
web2py 支援其中大多數,但整合將非常棘手。
使用 jQuery 使用 web2py JSON 服務
從 web2py 返回 JSON 形式的方法有很多,但這裡我們考慮 JSON 服務的情況。例如:
def consumer():return dict()@service.json def get_days():return ["Sun", "Mon", "Tues", "Wed", "Thurs", "Fri", "Sat"] def call():return service()
在這裡,我們觀察到:
該函式僅返回一個空字典以呈現檢視,該檢視將使用該服務。
get_days 定義了服務,並且函式呼叫公開了所有註冊的服務。
get_days 不需要在控制器中,也可以在模型中。
call 始終位於 default.py 腳手架控制器中。
包含使用者操作的檢視如下:
{{extend 'layout.html'}}
<div id = "target"></div>
<script>
jQuery.getJSON("{{= URL('call',args = ['json','get_days'])}}",
function(msg){
jQuery.each(msg, function(){ jQuery("#target").
append(this + "<br />"); } )
}
);
</script>
jQuery.getJSON 的第一個引數是以下服務的 URL:http://127.0.0.1:8000/app/default/call/json/get_days
這始終遵循以下模式:
http://<domain>/<app>/<controller>/call/<type>/<service>
URL 位於{{...}}之間,因為它是伺服器端解析的,而其他所有內容都在客戶端執行。jQuery.getJSON 的第二個引數是一個回撥函式,它將傳遞 JSON 響應。
在這種情況下,回撥函式遍歷響應中的每個專案(作為字串的星期列表),並將每個字串附加到<div id = "target">後面,並在後面加上<br/>。
這樣,web2py 使用jQuery.getJSON管理 Web 服務的實現。
Web2py - 新增 Ajax 效果
在本章中,我們將討論jQuery外掛與web2py整合的示例。這些外掛有助於使表單和表格對使用者更具互動性和友好性,從而提高應用程式的可用性。
特別是,我們將學習
如何使用互動式新增選項按鈕改進多選下拉列表,
如何用滑塊替換輸入欄位,以及
如何使用jqGrid和WebGrid顯示錶格資料。
儘管 web2py 是一個伺服器端開發元件,但welcome腳手架應用程式包含基本jQuery庫。此腳手架 web2py 應用程式“welcome”包含一個名為views/web2py_ajax.html的檔案。
檢視的內容如下:
<script type = "text/javascript"><!--
// These variables are used by the web2py_ajax_init function in web2py_ajax.js
(which is loaded below).
var w2p_ajax_confirm_message = "{{= T('Are you sure you want to delete this object?')}}";
var w2p_ajax_disable_with_message = "{{= T('Working...')}}";
var w2p_ajax_date_format = "{{= T('%Y-%m-%d')}}";
var w2p_ajax_datetime_format = "{{= T('%Y-%m-%d %H:%M:%S')}}";
var ajax_error_500 = '{{=T.M('An error occured, please [[reload %s]] the page') %
URL(args = request.args, vars = request.get_vars) }}'
//--></script>
{{
response.files.insert(0,URL('static','js/jquery.js'))
response.files.insert(1,URL('static','css/calendar.css'))
response.files.insert(2,URL('static','js/calendar.js'))
response.files.insert(3,URL('static','js/web2py.js'))
response.include_meta()
response.include_files()
}}
該檔案包含 JavaScript 和 AJAX 實現。web2py 將阻止使用者使用其他 AJAX 庫(如 Prototype、ExtJS),因為它始終觀察到實現此類庫更容易。
JQuery 效果
<select multiple = "true">..</select>的預設呈現被認為使用起來不太直觀,尤其是在需要選擇非連續選項時。這不能稱為 HTML 的缺點,而是大多數瀏覽器的設計不佳。可以使用 JavaScript 覆蓋多選的顯示方式。這可以使用名為jquery.multiselect.js的 jQuery 外掛來實現。
為此,使用者應從http://abeautifulsite.net/2008/04/jquery-multiselect下載外掛jquery.muliselect.js,並將相應的檔案放入static/js/jquery.multiselect.js和static/css/jquery.multiselect.css。
示例
應在相應的檢視中{{extend ‘layout.html’}}之前新增以下程式碼
{{
response.files.append('https://ajax.googleapis.com/ajax\
/libs/jqueryui/1.8.9/jquery-ui.js')
response.files.append('https://ajax.googleapis.com/ajax\
/libs/jqueryui/1.8.9/themes/ui-darkness/jquery-ui.css')
response.files.append(URL('static','js/jquery.multiSelect.js'))
response.files.append(URL('static','css/jquery.\multiSelect.css'))
}}
將以下內容放在{{extend 'layout.html'}}之後:
<script>
jQuery(document).ready(function(){jQuery('[multiple]').multiSelect();});
</script>
這將有助於為給定表單設定multiselect的樣式
控制器
def index():
is_fruits = IS_IN_SET(['Apples','Oranges','Bananas','Kiwis','Lemons'], multiple = True)
form = SQLFORM.factory(Field('fruits','list:string', requires = is_fruits))
if form.accepts(request,session):response.flash = 'Yummy!'
return dict(form = form)
可以使用以下檢視嘗試此操作:
{{
response.files.append('https://ajax.googleapis.com/ajax\
/libs/jqueryui/1.8.9/jquery-ui.js')
response.files.append('https://ajax.googleapis.com/ajax\
/libs/jqueryui/1.8.9/themes/ui-darkness/jquery-ui.css')
response.files.append(URL('static','js/jquery.multiSelect.js'))
response.files.append(URL('static','css/jquery.\multiSelect.css'))
}}
{{extend 'layout.html}}
<script>
jQuery(document).ready(function(){jQuery('[multiple]'). multiSelect();});
</script>
{{= form}}
輸出的螢幕截圖如下:
下表列出了一些有用的 Jquery 事件:
| 序號 | 事件及用法 |
|---|---|
| 1 | onchange 元素更改時執行 |
| 2 | onsubmit 提交表單時執行 |
| 3 | onselect 選擇元素時執行 |
| 4 | onblur 元素失去焦點時執行 |
| 5 | onfocus 元素獲得焦點時執行 |
JQuery 和 Ajax-jqGrid
jqGrid 是一個基於 jQuery 構建的啟用 Ajax 的 JavaScript 控制元件,它提供了一種表示和操作表格資料的解決方案。jqGrid是一個客戶端解決方案,它透過 Ajax 回撥動態載入資料,從而提供分頁、搜尋彈出視窗、內聯編輯等功能。
jqGrid 整合到 PluginWiki 中,但在這裡,我們將它作為 web2py 程式(不使用該外掛)的獨立程式進行討論。jqGrid 值得專門寫一本書,但在這裡我們只討論其基本功能和最簡單的整合。
jqGrid 的語法如下:
def JQGRID( table, fieldname = None, fieldvalue = None, col_widths = [], colnames = [], _id = None, fields = [], col_width = 80, width = 700, height = 300, dbname = 'db' ):
Web2py - 元件
元件定義為 Web 頁面的功能部分,它可以自主工作。它可以由嵌入在 Web 頁面中的模組、控制器和檢視組成。應用程式中的元件必須是本地化的標籤,並且效能被認為獨立於模組。
在 web2py 中,主要關注的是使用載入到頁面中並透過 AJAX 與元件控制器通訊的元件。
web2py 包含一個名為LOAD的函式,該函式使元件的實現變得容易,無需顯式使用 JavaScript 或 AJAX 程式設計。
考慮一個名為“test”的簡單 Web 應用程式,該應用程式使用檔案“models/db_comments.py”中的自定義模型擴充套件 web2py 應用程式。
db.define_table(
'comment_post', Field('body','text',
label = 'Your comment'),auth.signature
)
以上程式碼將建立一個名為“comment_post”的表,並具有正確的表定義。該操作將藉助“controllers/comments.py”中的函式來實現。
def post():
return dict(
form = SQLFORM(db.comment_post).process(),
comments = db(db.comment_post).select()
)
相應的檢視將顯示為:
{{extend 'layout.html'}}
{{for post in comments:}}
<div class = "post">
On {{= post.created_on}} {{= post.created_by.first_name}}
says <span class = "post_body">{{= post.body}}</span>
</div>
{{pass}}
{{= form}}
可以使用給定 URL 訪問該頁面:http://127.0.0.1:8000/test/comments/post
上面提到的方法是訪問檢視的傳統方法,可以透過實現 LOAD 函式來更改它。
這可以透過建立一個副檔名為“.load”的新檢視來實現,該檢視不擴展布局。
建立的新檢視將為"views/comments/post.load":
<div class = "post">
On {{= post.created_on}} {{= post.created_by.first_name}}
says <blockquote class = "post_body">{{= post.body}}</blockquote>
</div>
{{pass}}
{{= form}}
訪問該頁面的 URL 將為:http://127.0.0.1:8000/test/comments/post.load
LOAD 元件可以嵌入到 web2py 應用程式的任何其他頁面中。這可以透過使用以下語句來完成。
{{= LOAD('comments','post.load',ajax = True)}}
例如,可以編輯控制器如下:
def index(): return dict()
在檢視中,我們可以新增元件:
{{extend 'layout.html'}}
{{= LOAD('comments','post.load',ajax = True)}}
可以使用 URL 訪問該頁面:http://127.0.0.1:8000/test/default/index
元件外掛
元件外掛是唯一定義元件的外掛。元件直接使用其模型定義訪問資料庫。
如前面的示例中所述,可以在模型部分將註釋元件轉換為comments_plugin:
"models/plugin_comments.py":
db.define_table(
'plugin_comments_comment',
Field('body','text', label = 'Your comment'),
auth.signature
)
控制器將包含以下外掛:
def plugin_comments():
return LOAD('plugin_comments','post',ajax = True)
Web2py - 部署
在 Ubuntu(Linux)中安裝 web2py
以下步驟用於在 Ubuntu 桌面中安裝 web2py。
步驟 1 - 下載 web2py
cd /home mkdir www-dev cd www-dev wget http://www.web2py.com/examples/static/web2py_src.zip
步驟 2 - 下載完成後,解壓縮它。
unzip -x web2py_src.zip
步驟 3 - 可選地為 Python 安裝 tk 庫,如果您需要訪問 GUI。
sudo apt-get install python-tk
步驟 4 - 要啟動 web2py,請訪問 web2py 目錄並執行 web2py。
cd web2py python web2py.py
GUI 將如下所示:
安裝完成後,每次執行web2py時,都會提示您選擇密碼。此密碼是您的管理員密碼。如果密碼為空,則管理員介面將被停用。
伺服器啟動後,web2py將重定向到以下URL所示的螢幕:http://127.0.0.1:8000/
這將表明web2py在Ubuntu桌面中完美執行。
Ubuntu生產環境部署
步驟1 - 安裝執行web2py所需的所有模組。
安裝postgreSQL
sudo apt-get install postgresql
解壓縮並開啟ssh-server
sudo apt-get install unzip sudo apt-get install openssh-server
安裝Apache 2和mod-wsgi
sudo apt-get install apache2 sudo apt-get install libapache2-mod-wsgi
步驟2 - 將web2py安裝到/home/www-data
這有助於在生產環境中正確部署。
sudo apt-get install unzip sudo apt-get install openssh-server cd /home sudo mkdir www-data cd www-data
從web2py網站獲取web2py原始碼 -
sudo wget http://web2py.com/examples/static/web2py_src.zip sudo unzip web2py_src.zip sudo chown -R www-data:www-data web2py
步驟3 - 建立自簽名證書。SSL證書應從受信任的證書頒發機構獲取。在SSL資料夾中維護證書。
步驟4 - 根據生產環境的要求編輯Apache配置。
步驟5 - 重啟Apache伺服器並驗證給定IP地址的生產環境是否有效。
在Windows上安裝web2py
雖然Windows環境存在二進位制發行版(打包可執行檔案和標準庫),但web2py是開源的,可以與普通的Python安裝一起使用。
這種方法允許使用web2py的最新版本,並自定義要使用的Python模組。
步驟1 - 從web2py官方網站下載原始碼包 - http://www.web2py.com/examples/static/web2py_src.zip 並解壓縮。
由於web2py不需要安裝,使用者可以將其解壓縮到任何資料夾中。
步驟2 - 要啟動它,請雙擊web2py.py。從控制檯 -
cd c:\web2py c:\python27\python.exe web2py.py
步驟3 - 這裡可以新增命令列引數(-a設定管理員密碼,-p指定備用埠)。啟動選項可以透過 -
C:\web2py>c:\python27\python.exe web2py.py --help
注意
web2py是用Python編寫的,Python是一種可移植的、解釋型的、動態的語言,不需要編譯或複雜的安裝即可執行。
它使用虛擬機器(如Java和.Net),並且可以在您執行指令碼時動態地透明地將您的原始碼位元組編譯。
web2py在資料庫和測試方面的功能
它是一個名為SQLDesigner的軟體,有助於建立web2py模型並生成相應的程式碼。下面是一些截圖 -
SQLDesigner有助於以簡單的方式維護表之間的關係,並在給定應用程式的模型中生成相應的程式碼。
功能測試
功能測試涉及測試元件或整個系統的功能。它可以基於需求和業務流程。
web2py帶有一個名為gluon.contrib.webclient的模組,它可以在遠端和本地web2py應用程式中執行功能測試。它基本上是為了理解web2py會話和回發而設計的。
它只需要匯入包,這樣功能測試就可以在給定的模組上實現。
匯入包的語法如下 -
from gluon.contrib.webclient import WebClient
Web2py - 安全性
在前面的章節中,對web2py與各種工具的整合進行了完整的介紹。開發web2py應用程式的主要關注點包括從使用者的角度考慮安全性。
web2py的獨特功能如下 -
使用者可以輕鬆學習實現。它不需要安裝和依賴項。
自發布之日起就一直穩定。
web2py輕量級,包含資料抽象層和模板語言庫。
它藉助Web伺服器閘道器介面工作,該介面充當Web伺服器和應用程式之間的通訊橋樑。
開放式Web應用程式安全專案(OWASP)是一個社群,它列出了Web應用程式的安全漏洞。
安全漏洞
關於OWASP,下面討論了與Web應用程式相關的問題以及web2py如何克服這些問題。
跨站點指令碼
也稱為XSS。每當應用程式獲取使用者提供的資料並將其傳送到使用者的瀏覽器而沒有對內容進行編碼或驗證時,就會發生這種情況。攻擊者執行指令碼以使用跨站點指令碼注入蠕蟲和病毒。
web2py透過阻止檢視中所有呈現的變數來幫助防止XSS。
資訊洩露
有時,應用程式會洩漏有關內部工作原理、隱私和配置的資訊。攻擊者利用此資訊來破壞敏感資料,這可能導致嚴重攻擊。
web2py透過票據系統防止這種情況。它記錄所有錯誤,並向註冊錯誤的使用者發出票據。這些錯誤只有管理員可以訪問。
身份驗證錯誤
帳戶憑據通常不受保護。攻擊者會危及密碼、身份驗證令牌以竊取使用者的身份。
web2py提供了一種用於管理介面的機制。當客戶端不是“localhost”時,它還會強制使用安全會話。
不安全的通訊
有時應用程式無法加密網路流量。必須管理流量以保護敏感通訊。
web2py提供啟用SSL的證書來提供通訊加密。這也有助於維護敏感通訊。
URL訪問限制
Web應用程式通常透過阻止向某些使用者顯示連結和URL來保護敏感功能。攻擊者可以透過使用某些資訊操縱URL來嘗試破壞某些敏感資料。
在wb2py中,URL對映到模組和函式,而不是給定的檔案。它還包括一個機制,該機制指定哪些函式是公開的,哪些函式保持私有。這有助於解決問題。