Pyramid 使用SQLAlchemy

2023-03-30 17:46 更新

在本章中,我们将学习如何使用关系型数据库作为Pyramid网络应用程序的后端。Python可以使用相应的DB-API兼容的连接器模块或驱动程序与几乎所有的关系型数据库进行交互。然而,我们将使用 SQLAlchemy 库作为Python代码和数据库之间的接口(我们将使用SQLite数据库,因为Python对它有内置的支持)。SQLAlchemy是一个流行的SQL工具箱和对象关系映射器。

对象关系映射是一种编程技术,用于在面向对象编程语言中不兼容的类型系统之间转换数据。通常,在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 的一个子类,被映射到数据库中的一个 学生 表。 学生 类中的属性与目标表中的列的数据类型相对应。请注意,id属性与书表中的主键相对应。

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 )来确认。

Python Pyramid - 使用SQLAlchemy

现在我们将定义视图函数,用于对上述数据库中的学生表进行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 route,并注册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='http://localhost:6543/')

确保在配置中添加添加路由,映射到/添加URL模式。

config.add_route('add','/add')

输出

如果我们启动服务器并在浏览器中打开 http://localhost:6543/new ,输入表单将显示如下—-。

Python Pyramid - 使用SQLAlchemy

填写表格并按下 “提交 “按钮。add()视图将被调用,一条新记录将被添加到学生表中。重复这个过程几次以添加一些记录。Here is a sample data −

Python Pyramid - 使用SQLAlchemy

显示所有记录的列表

学生模型的所有对象(对应于学生表中的行)都是通过查询该模型获得的。

rows = session.query(Students).all()

每一行都被转换为一个dict对象,所有的dict对象都被追加到一个列表中,并作为一个上下文返回到list.html模板中,以HTML模板的形式显示。这个过程是由showall()视图函数执行的,与list route相关。

@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" rel="external nofollow" target="_blank" >Add new</a></h3>
   </body>
</html>

在配置中添加列表路由,并以’/’URL注册。

config.add_route('list', '/')

输出

启动服务器后在浏览器中打开 http://localhost:6543/ 。将显示学生表中的现有记录列表。

Python Pyramid - 使用SQLAlchemy

注意最后两列中的超链接。例如,”id=1 “前面的 “编辑 “链接指向 http://localhost:6543/show/1 。这些链接是为了执行更新和删除操作。

更新现有记录

在/show/1的URL中,有一个尾部的路径参数。它被映射到配置中的’show’路线。

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

Python Pyramid - 使用SQLAlchemy

改变标记文本字段中的值并按提交。表格被重定向到/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/')

返回语句将浏览器重定向到’/’URL,它指向list()函数并显示更新的标记列表。

Python Pyramid - 使用SQLAlchemy

确保在运行前将更新路线添加到配置中。

config.add_route('update', '/update')

删除一条记录

要删除标记表中某一行对应的记录,请按照最后一列中的删除链接。例如,点击第三行的Delete会发出 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/" rel="external nofollow" target="_blank" >Click here to refresh the mark list</a>
</body>
</html>

很明显,删除路径必须被添加到应用程序配置注册表中。

config.add_route('delete', '/delete/{id}')

输出

记录删除动作的结果如下所示

Python Pyramid - 使用SQLAlchemy

采取以下步骤来执行上述解释的活动

  • 在Pyramid虚拟环境中创建一个名为 testapp 的文件夹。
  • 在 testapp 中,创建 templates 文件夹。
  • 在testapp中创建一个空白的 __init__.py ,使其成为一个包。
  • 将marklist.html、myform.html、showform.html和delete.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。一个只有标题而没有记录的表格将被显示。
  • 按照表格下方的 “添加新 “链接来添加记录。
  • 点击表格中的 “编辑 “链接来更新记录。
  • 点击表格中的 “删除 “链接,删除选定的记录。


以上内容是否对您有帮助:
在线笔记
App下载
App下载

扫描二维码

下载编程狮App

公众号
微信公众号

编程狮公众号