- Python Pyramid 教程
- Python Pyramid - 首頁
- Python Pyramid - 概述
- Pyramid - 環境設定
- Python Pyramid - Hello World
- Pyramid - 應用配置
- Python Pyramid - URL 路由
- Python Pyramid - 檢視配置
- Python Pyramid - 路由字首
- Python Pyramid - 模板
- Pyramid - HTML 表單模板
- Python Pyramid - 靜態資源
- Python Pyramid - 請求物件
- Python Pyramid - 響應物件
- Python Pyramid - 會話
- Python Pyramid - 事件
- Python Pyramid - 訊息閃現
- Pyramid - 使用SQLAlchemy
- Python Pyramid - Cookiecutter
- Python Pyramid - 建立專案
- Python Pyramid - 專案結構
- Python Pyramid - 包結構
- 手動建立專案
- 命令列 Pyramid
- Python Pyramid - 測試
- Python Pyramid - 日誌記錄
- Python Pyramid - 安全性
- Python Pyramid - 部署
- Python Pyramid 有用資源
- Python Pyramid - 快速指南
- Python Pyramid - 有用資源
- Python Pyramid - 討論
Python Pyramid - 使用SQLAlchemy
本章我們將學習如何使用關係資料庫作為 Pyramid Web 應用的後端。Python 可以使用相應的 DB-API 相容聯結器模組或驅動程式與幾乎所有關係資料庫進行互動。但是,我們將使用SQLAlchemy庫作為 Python 程式碼和資料庫之間的介面(我們將使用 SQLite 資料庫,因為 Python 對其有內建支援)。SQLAlchemy 是一個流行的 SQL 工具包和物件關係對映器。
物件關係對映 (ORM) 是一種程式設計技術,用於在面向物件程式語言中轉換不相容型別系統之間的資料。通常,面嚮物件語言(如 Python)中使用的型別系統包含非標量型別。但是,大多數資料庫產品(如 Oracle、MySQL 等)中的資料型別是原始型別,例如整數和字串。
在 ORM 系統中,每個類都對映到底層資料庫中的一個表。ORM 代替你編寫繁瑣的資料庫介面程式碼,它為你處理這些問題,而你可以專注於系統邏輯的程式設計。
為了使用 SQLAlchemy,我們需要首先使用 PIP 安裝程式安裝該庫。
pip install sqlalchemy
SQLAlchemy 旨在與為特定資料庫構建的 DBAPI 實現一起工作。它使用方言系統與各種型別的 DBAPI 實現和資料庫進行通訊。所有方言都需要安裝相應的 DBAPI 驅動程式。
以下是一些包含的方言:
Firebird
Microsoft SQL Server
MySQL
Oracle
PostgreSQL
SQLite
Sybase
資料庫引擎
由於我們將使用 SQLite 資料庫,我們需要為名為test.db的資料庫建立一個數據庫引擎。從sqlalchemy模組匯入create_engine()函式。
from sqlalchemy import create_engine
from sqlalchemy.dialects.sqlite import *
SQLALCHEMY_DATABASE_URL = "sqlite:///./test.db"
engine = create_engine(SQLALCHEMY_DATABASE_URL, connect_args = {"check_same_thread": False})
為了與資料庫互動,我們需要獲取其控制代碼。會話物件是資料庫的控制代碼。會話類使用sessionmaker()定義 - 一個可配置的會話工廠方法,它繫結到引擎物件。
from sqlalchemy.orm import sessionmaker, Session session = sessionmaker(autocommit=False, autoflush=False, bind=engine)
接下來,我們需要一個宣告性基類,它在宣告性系統中儲存類和對映表的目錄。
from sqlalchemy.ext.declarative import declarative_base Base = declarative_base()
模型類
Students(作為Base的子類)對映到資料庫中的students表。Students類中的屬性對應於目標表中列的資料型別。請注意,id 屬性對應於 book 表中的主鍵。
class Students(Base): __tablename__ = 'student' id = Column(Integer, primary_key=True, nullable=False) name = Column(String(63), unique=True) marks = Column(Integer) Base.metadata.create_all(bind=engine)
create_all()方法在資料庫中建立相應的表。可以使用 SQLite 視覺化工具(例如SQLiteStudio)進行確認。
現在,我們將定義檢視函式來對上述資料庫中的學生表執行 CRUD 操作(即新增、顯示、修改和刪除行)。
新增新的學生記錄
首先,我們將建立一個 HTML 表單模板,供使用者輸入學生資料,並定義一個呈現該模板的檢視。以下是myform.html模板
示例
<html> <body> <form method="POST" action="https://:6543/add"> <p>Student Id: <input type="text" name="id"/> </p> <p>student Name: <input type="text" name="name"/> </p> <p>Percentage: <input type="text" name="percent"/> </p> <p><input type="submit" value="Submit"> </p> </body> </html>
在 Pyramid 應用程式碼中,定義 index() 檢視函式來渲染上述表單。
from wsgiref.simple_server import make_server
from pyramid.config import Configurator
from pyramid.response import Response
from pyramid.view import view_config
@view_config(route_name='index', renderer='templates/myform.html')
def index(request):
return {}
在應用配置中,為該檢視註冊具有“/new”模式的路由,如下所示:
if __name__ == '__main__':
with Configurator() as config:
config.include('pyramid_jinja2')
config.add_jinja2_renderer(".html")
config.add_route('index', '/new')
config.scan()
app = config.make_wsgi_app()
server = make_server('0.0.0.0', 6543, app)
server.serve_forever()
由於上述模板中的 HTML 表單以 POST 動作提交到/add URL,我們需要將此 URL 對映到 add 路由,並註冊解析表單資料到 Students 類物件的 add() 檢視。此物件被新增到資料庫會話中,並且透過呼叫其 commit() 方法來完成操作。
@view_config(route_name='add', request_method='POST') def add(request): id=request.POST['id'] name=request.POST['name'] percent=int(request.POST['percent']) student=Students(id=id, name=name, percent=percent) session.add(student) session.commit() return HTTPFound(location='https://:6543/')
確保在配置中添加了 add 路由,並將其對映到 /add URL 模式。
config.add_route('add','/add')
輸出
如果我們啟動伺服器並在瀏覽器中開啟https://:6543/new,則將顯示如下所示的輸入表單:
填寫表單並按下“提交”按鈕。將呼叫 add() 檢視,並在 students 表中新增一條新記錄。重複此過程幾次以新增幾條記錄。這是一個示例資料:
顯示所有記錄列表
透過查詢模型獲得 Students 模型的所有物件(對應於 students 表中的行)。
rows = session.query(Students).all()
每行都轉換為一個 dict 物件,所有這些物件都附加到一個 dict 物件列表中,並作為上下文返回到 list.html 模板,以便以 HTML 模板的形式顯示。此過程由與 list 路由關聯的 showall() 檢視函式執行。
@view_config(route_name='list', renderer='templates/marklist.html')
def showall(request):
rows = session.query(Students).all()
students=[]
for row in rows:
students.append({"id":row.id, "name":row.name, "percent":row.percent})
return{'students':students}
示例
marklist.html模板將 Students 列表呈現為 HTML 表格。其 HTML/jinja2 指令碼如下:
<html>
<body>
<table border=1>
<thead>
<tr>
<th>Student ID</th>
<th>Student Name</th>
<th>percentage</th>
<th>Edit</th>
<th>Delete</th>
</tr>
</thead>
<tbody>
{% for Student in students %}
<tr>
<td>{{ Student.id }}</td> <td>{{ Student.name }}</td>
<td>{{ Student.percent }}</td>
<td><a href="/show/{{ Student.id }}">edit</a></td>
<td><a href="/delete/{{ Student.id }}">delete</a></td>
</tr>
{% endfor %}
</tbody>
</table>
<h3><a href="https://:6543/new">Add new</a></h3>
</body>
</html>
在配置中新增 list 路由,並將其註冊到 '/' URL。
config.add_route('list', '/')
輸出
啟動伺服器後,在瀏覽器中開啟https://:6543/。將顯示 students 表中現有記錄的列表。
請注意最後兩列中的超連結。例如,"id=1"之前的“編輯”連結指向https://:6543/show/1。這些連結旨在執行更新和刪除操作。
更新現有記錄
在 /show/1 URL 中,有一個尾隨路徑引數。它在配置中對映到“show”路由。
config.add_route('show', '/show/{id}')
此路由呼叫 show() 函式。它獲取與給定 id 引數對應的記錄,使用其內容填充 HTML 表單,並允許使用者更新 name 和/或 percent 欄位的值。
@view_config(route_name='show', renderer='templates/showform.html')
def show(request):
id=request.matchdict['id']
row = session.query(Students).filter(Students.id == id).first()
student={'id':row.id, 'name':row.name, 'percent':row.percent}
return {'student':student}
示例
showform.html 模板的 HTML/jinja2 程式碼如下:
<html>
<body>
<form method="POST" action="https://:6543/update">
<p>Student Id: <input type="text" name="id" value="{{ student.id }} " readonly/> </p>
<p>student Name: <input type="text" name="name" value="{{ student.name }}"/> </p>
<p>Percentage: <input type="text" name="percent" value="{{ student.percent }}"/> </p>
<p><input type="submit" value="Submit"> </p>
</body>
</html>
輸出
讓我們更新 id=3 的記錄。單擊相應的“編輯”連結以導航到https://:6543/show/3
更改分數文字欄位中的值並按下提交。表單將重定向到 /update URL,並呼叫 update() 檢視。它獲取提交的資料並更新相應物件,從而也更新 students 表中的底層行。
@view_config(route_name='update', request_method='POST') def update(request): id=int(request.POST['id']) student = session.query(Students).filter(Students.id == id).first() student.percent=int(request.POST['percent']) session.commit() return HTTPFound(location='https://:6543/')
return 語句將瀏覽器重定向回 '/' URL,該 URL 指向 list() 函式並顯示更新後的 marklist。
在執行之前,確保已將更新路由新增到配置中。
config.add_route('update', '/update')
刪除記錄
要刪除與 marklist 表中的一行對應的記錄,請單擊最後一列中的“刪除”連結。例如,單擊第 3 行中的“刪除”將發出https://:6543/delete/3 URL 並呼叫以下檢視函式:
@view_config(route_name='delete', renderer='templates/deleted.html')
def delete(request):
id=request.matchdict['id']
row = session.query(Students).filter(Students.id == id).delete()
return {'message':'Redcord has been deleted'}
示例
刪除與從 URL 解析的路徑引數對應的物件,並由以下模板deleted.html呈現相應的訊息:
<html>
<body>
<h3>{{ message}}</h3>
<br><br>
<a href="https://:6543/">Click here to refresh the mark list</a>
</body>
</html>
顯然,必須在應用配置登錄檔中新增 delete 路由。
config.add_route('delete', '/delete/{id}')
輸出
記錄刪除操作的結果如下所示:
請按照以下步驟執行上述活動:
在 Pyramid 虛擬環境中建立一個名為testapp的資料夾
在testapp內,建立templates資料夾。
在 testapp 中建立一個空的__init__.py,使其成為一個包。
將 marklist.html、myform.html、showform.html 和 deleted.html 檔案放入“testapp\templates”資料夾。這些檔案的程式碼已在上面給出。
將以下程式碼儲存為testapp中的models.py。
from sqlalchemy.dialects.sqlite import *
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.orm import Session
from sqlalchemy import Column, Integer, String
SQLALCHEMY_DATABASE_URL = "sqlite:///./test.db"
Base = declarative_base()
class Students(Base):
__tablename__ = 'student'
id = Column(Integer, primary_key=True, nullable=False)
name = Column(String(63), unique=True)
percent = Column(Integer)
def getsession():
engine = create_engine(
SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False}
)
Base.metadata.create_all(bind=engine)
Session = sessionmaker(bind = engine)
session = Session()
return session
將以下程式碼儲存為testapp資料夾中的views.py。
from pyramid.response import Response
from pyramid.view import view_config
from pyramid.httpexceptions import HTTPFound
from models import Students
from main import session
@view_config(route_name='list', renderer='templates/marklist.html')
def showall(request):
rows = session.query(Students).all()
students=[]
for row in rows:
students.append({"id":row.id, "name":row.name, "percent":row.percent})
return{'students':students}
@view_config(route_name='index', renderer='templates/myform.html')
def index(request):
return {}
@view_config(route_name='add', request_method='POST')
def add(request):
id=request.POST['id']
name=request.POST['name']
percent=int(request.POST['percent'])
student=Students(id=id, name=name, percent=percent)
session.add(student)
session.commit()
return HTTPFound(location='https://:6543/')
@view_config(route_name='update', request_method='POST')
def update(request):
id=int(request.POST['id'])
student = session.query(Students).filter(Students.id == id).first()
student.percent=int(request.POST['percent'])
session.commit()
return HTTPFound(location='https://:6543/')
@view_config(route_name='show', renderer='templates/showform.html')
def show(request):
id=request.matchdict['id']
row = session.query(Students).filter(Students.id == id).first()
student={'id':row.id, 'name':row.name, 'percent':row.percent}
return {'student':student}
@view_config(route_name='delete', renderer='templates/deleted.html')
def delete(request):
id=request.matchdict['id']
row = session.query(Students).filter(Students.id == id).delete()
return {'message':'Redcord has been deleted'}
將以下程式碼儲存為 testapp 資料夾中的 main.py。
from wsgiref.simple_server import make_server
from pyramid.config import Configurator
from models import getsession
session=getsession()
if __name__ == '__main__':
with Configurator() as config:
config.include('pyramid_jinja2')
config.add_jinja2_renderer(".html")
config.add_route('list', '/')
config.add_route('index', '/new')
config.add_route('add','/add')
config.add_route('show', '/show/{id}')
config.add_route('update', '/update')
config.add_route('delete', '/delete/{id}')
config.scan('testapp')
app = config.make_wsgi_app()
server = make_server('0.0.0.0', 6543, app)
server.serve_forever()
從命令提示符執行main.py。
Python main.py
在瀏覽器視窗中使用https://:6543/ URL。將顯示一個只有標題而沒有記錄的表格。
單擊表格下面的“新增新”連結以新增記錄。
單擊表格中的“編輯”連結以更新記錄。
單擊表格中的“刪除”連結以刪除選定的記錄。