- 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 工具包和对象关系映射器。
对象关系映射是一种编程技术,用于在面向对象编程语言中的不兼容类型系统之间转换数据。通常,像 Python 这样的面向对象语言中使用的类型系统包含非标量类型。然而,大多数数据库产品如Oracle、MySQL等中的数据类型都是整数、字符串等原始类型。
在 ORM 系统中,每个类都映射到底层数据库中的一个表。ORM 无需您自己编写繁琐的数据库接口代码,而是会为您处理这些问题,同时您可以专注于对系统逻辑进行编程。
为了使用 SQLALchemy,我们需要首先使用 PIP 安装程序安装该库。
pip install sqlalchemy
SQLAlchemy 旨在与为特定数据库构建的 DBAPI 实现一起运行。它使用方言系统与各种类型的 DBAPI 实现和数据库进行通信。所有方言都要求安装适当的 DBAPI 驱动程序。
以下是包含的方言 -
火鸟
微软SQL服务器
MySQL
甲骨文
PostgreSQL
SQLite
赛贝斯
数据库引擎
由于我们将使用 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类中的属性对应于目标表中列的数据类型。请注意,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 Visual工具(例如SQLiteStudio)进行确认。
现在我们将定义视图函数,用于对上述数据库中的学生表执行 CRUD 操作(即添加、显示、修改和删除行)。
添加新学生记录
首先,我们将创建一个 HTML 表单模板,供用户输入学生数据并定义一个呈现该模板的视图。这是myform.html模板
例子
<html> <body> <form method="POST" action="http://localhost: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 类的对象。该对象被添加到数据库会话中,并通过调用其 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='http://localhost:6543/')
确保添加路由已添加到配置中,映射到 /add URL 模式。
config.add_route('add','/add')
输出
如果我们启动服务器并在浏览器中打开http://localhost:6543/new,条目表单将显示如下 -
填写表格并按“提交”按钮。add() 视图将被调用,一条新记录将被添加到学生表中。重复该过程几次以添加一些记录。这是一个示例数据 -
显示所有记录列表
Students 模型的所有对象(对应学生表中的行)都是通过查询模型获得的。
rows = session.query(Students).all()
每一行都转换为一个 dict 对象,所有行都附加到 dict 对象列表中,并作为上下文返回到 list.html 模板,以 HTML 模板的形式显示。该过程由与列表路由关联的 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模板将学生列表呈现为 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="http://localhost:6543/new">Add new</a></h3> </body> </html>
在配置中添加列表路由并使用“/” URL 进行注册。
config.add_route('list', '/')
输出
启动服务器后在浏览器中打开http://localhost:6543/ 。将显示学生表中现有记录的列表。
请注意最后两列中的超链接。例如,“id=1”之前的“edit”链接指向http://localhost:6543/show/1。这些链接旨在执行更新和删除操作。
更新现有记录
在 /show/1 URL 中,有一个尾随路径参数。它映射到配置中的“显示”路由。
config.add_route('show', '/show/{id}')
该路由调用 show() 函数。它获取与给定 id 参数相对应的记录,用其内容填充 HTML 表单,并允许用户更新名称和/或百分比字段的值。
@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="http://localhost: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 的记录。单击相应的编辑链接导航到http://localhost:6543/show/3
更改标记文本字段中的值并按提交。该表单被重定向到 /update URL 并调用 update() 视图。它获取提交的数据并更新相应的对象,从而学生表中的基础行也被更新。
@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='http://localhost:6543/')
return 语句将浏览器重定向回“/” URL,该 URL 指向 list() 函数并显示更新后的标记列表。
确保在运行之前将更新路由添加到配置中。
config.add_route('update', '/update')
删除一条记录
要删除与标记列表中的行相对应的记录,请点击最后一列中的删除链接。例如,单击第三行中的“删除”会发出http://localhost: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="http://localhost:6543/">Click here to refresh the mark list</a> </body> </html>
显然,删除路由必须添加到应用程序配置注册表中。
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='http://localhost: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='http://localhost: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
在浏览器窗口中使用http://localhost:6543/ URL。将显示一个仅包含标题而没有记录的表格。
点击表格下方的“添加新”链接来添加记录。
单击表中的“编辑”链接以更新记录。
单击表中的“删除”链接可删除所选记录。