在第一篇文章这个由四部分组成的系列比较不同的 Python Web 框架中,我解释了如何在FlaskWeb 框架中创建一个待办事项列表 Web 应用程序。在第二篇文章中,我将使用Pyramidweb 框架执行相同的任务。以后的文章会关注Tornado和Django;随着我的进展,我将探索它们之间的更多差异。

安装、启动、配置

Pyramid 自我描述为“从小处着手,完成大处,保持完成的框架”,Pyramid 与 Flask 非常相似,只需很少的努力即可启动和运行。事实上,在构建此应用程序时,您会发现许多相同的模式。然而,两者之间的主要区别在于 Pyramid 附带了几个有用的实用程序,我将在稍后对其进行描述。

首先,创建一个虚拟环境并安装软件包。

$ mkdir 金字塔_todo

$ cd 金字塔_todo

$ pipenv 安装 --python 3.6

$ pipenv 外壳

(pyramid-someHash) $ pipenv 安装金字塔

与 Flask 一样,创建setup.py文件以使您构建的应用程序成为易于安装的 Python 发行版是很聪明的。

# setup.py

从 setuptools 导入设置,找到_packages

需要 \u003d [

'金字塔',

'paster_pastedeploy',

'金字塔-ipython',

“女服务员”

]

设置(

名称\u003d'金字塔_todo',

版本\u003d'0.0',

description\u003d'A To-Do List build with Pyramid',

作者\u003d'<你的名字>',

作者_email\u003d'<您的电子邮件>',

关键字\u003d'网络金字塔塔',

包\u003dfind_packages(),

包括\包\数据\u003d真,

安装_requires\u003d需要,

入口_points\u003d{

'paste.app_factory': [

'main u003d todo:main',

]

}

)

更多 Python 资源

  • 什么是 IDE?

  • 备忘单:适用于初学者的 Python 3.7

  • 顶级 Python GUI 框架

  • 下载:7 个必不可少的 PyPI 库

  • 红帽开发者

  • 最新 Python 内容

靠近末尾的entry_points部分设置了其他服务可以使用的应用程序的入口点。这允许plaster_pastedeploy包访问应用程序中的main函数,以构建应用程序对象并为其提供服务。 (我稍后会回到这个话题。)

当您安装pyramid时,您还获得了一些 Pyramid 特定的 shell 命令;主要需要注意的是pservepshellpserve将采用指定为参数的 INI 样式配置文件并在本地为应用程序提供服务。pshell也将配置文件作为参数,但它不会为应用程序提供服务,而是会打开一个 Python shell,该 shell 知道应用程序及其内部配置。

配置文件非常重要,因此值得仔细查看。 Pyramid 可以从环境变量或配置文件中获取其配置。为避免过多混淆在哪里,在本教程中,您将在配置文件中编写大部分配置,仅在虚拟环境中设置少数敏感的配置参数。

创建一个名为config.ini的文件

[应用程序:主]

使用 \u003d 鸡蛋:待办事项

pyramid.default_locale_name \u003d en

[服务器:主]

使用 \u003d egg:waitress#main

听\u003d本地主机:6543

这说明了几件事:

  • 实际应用将来自安装在环境中的todo包中的main函数

  • 服务这个应用,使用安装在环境中的waitress包,服务于localhost端口6543

在为应用程序提供服务和进行开发工作时,设置日志记录有助于您查看正在发生的事情。以下配置将处理应用程序的日志记录:

#继续...

[记录器]

键\u003d根,待办事项

[处理程序]

键 \u003d 控制台

[格式化程序]

键\u003d通用

[记录器_root]

级别 \u003d 信息

处理程序 \u003d 控制台

[记录器_所有]

级别\u003d调试

处理程序 \u003d

质量名 \u003d 全部

[处理程序_控制台]

类 \u003d 流处理程序

args \u003d (sys.stderr,)

级别 \u003d NOTSET

格式化程序 \u003d 通用

[格式化程序_通用]

格式 \u003d %(asctime)s %(levelname)-5.5s [%(name)s:%(lineno)s][%(threadName)s] %(message)s

简而言之,此配置要求将与应用程序有关的所有内容记录到控制台。如果您想要更少的输出,请将日志记录级别设置为WARN,这样只有在出现问题时才会触发消息。

因为 Pyramid 是为一个不断增长的应用程序设计的,所以计划一个可以支持这种增长的文件结构。当然,Web 应用程序可以随心所欲地构建。通常,您要涵盖的概念块将包含:

  • Models 用于包含处理数据表示的代码和逻辑

  • Views 用于与请求-响应周期有关的代码和逻辑

  • Routes 用于访问应用程序功能的路径

  • 脚本 用于可能用于配置或管理应用程序本身的任何代码

鉴于上述情况,文件结构可能如下所示:

安装程序.py

配置文件

全部 /

__init__.py

模型.py

路线.py

视图.py

脚本/

就像 Flask 的app对象一样,Pyramid 有自己的中心配置。它来自它的config模块,被称为Configurator对象。该对象将处理从路由配置到指向模型和视图所在位置的所有事情。所有这些都是在__init__.py文件中名为todo的内部目录中完成的。

# 待办事项/__init__.py

从 pyramid.config 导入配置器

def main(全局_config,**设置):

"""返回 Pyramid WSGI 应用程序。"""

配置\u003d配置器(设置\u003d设置)

config.scan()

返回 config.make_wsgi_app()

main函数从您的环境中查找一些全局配置,以及通过您在运行应用程序时提供的特定配置文件获得的任何设置。它采用这些设置并使用它们来构建Configurator对象的实例,该对象(出于所有意图和目的)是您的应用程序的工厂。最后,config.scan()会查找您想要附加到应用程序的任何视图,这些视图被标记为 Pyramid 视图。

哇,配置太多了。

使用路由和视图

现在已经完成了大部分配置,您可以开始向应用程序添加功能。功能以外部客户端可以访问的 URL 路由的形式出现,然后映射到 Python 可以运行的函数。

对于 Pyramid,所有功能都必须以某种方式、形状或形式添加到Configurator。例如,假设您要构建与使用 Flask 构建的相同的简单hello_world视图,映射到/的路由。使用 Pyramid,您可以使用.add_route()方法将/路由注册到Configurator。此方法将您要添加的路由的名称以及访问该路由必须匹配的实际模式作为参数。对于这种情况,请将以下内容添加到您的Configurator:

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

在您创建一个视图并将其附加到该路由之前,进入您的应用程序的该路径是开放且单独的。添加视图时,请确保在参数列表中包含request对象。每个 Pyramid 视图_必须_将request对象作为其第一个参数,因为当 Pyramid 调用视图时,它作为第一个参数传递给视图。

Pyramid 视图与 Flask 共享的一个相似之处是您可以使用装饰器将函数标记为视图。具体来说,来自pyramid.view@view_config装饰器。

views.py中,构建您想在世界上看到的视图。

从 pyramid.view 导入视图_config

@view_config(route_name\u003d"hello", renderer\u003d"string")

def hello_world(请求):

"""打印'你好,世界!'作为响应体。"""

返回“你好,世界!”

使用@view_config装饰器,您至少必须指定将映射到此特定视图的路由的名称。如果需要,您可以将view_config装饰器堆叠在一起以映射到多条路线,但您必须至少有一个来连接视图,并且每个都必须包含路线的名称。 [注意:“连接查看视图”的措辞是否正确?]

另一个参数renderer是可选的,但_不是真的_。如果不指定渲染器,则必须使用来自pyramid.responseResponse对象故意构造要发送回客户端的 HTTP 响应。通过将renderer指定为字符串,Pyramid 知道获取此函数返回的任何内容并将其包装在具有text/plain的 MIME 类型的同一Response对象中。默认情况下,Pyramid 允许您使用stringjson作为渲染器。如果您已将模板引擎附加到您的应用程序,因为您希望 Pyramid 也生成您的 HTML,您可以直接指向您的 HTML 模板作为您的渲染器。

第一个视图完成。这是__init__.py现在与附加路线的样子。

# 在 __init__.py

从 pyramid.config 导入配置器

def main(全局_config,**设置):

"""返回 Pyramid WSGI 应用程序。"""

配置\u003d配置器(设置\u003d设置)

config.add_route('你好', '/')

config.scan()

返回 config.make_wsgi_app()

壮观!到达这里并不是一件容易的事,但是现在您已经设置好了,您可以轻松地添加功能。

平滑毛边

现在应用程序只有一个路由,但是很容易看到一个大型应用程序可以有几十个甚至数百个路由。将它们全部包含在与您的中央配置相同的main函数中并不是最好的主意,因为它会变得混乱。值得庆幸的是,通过对应用程序进行一些调整来包含路由是相当容易的。

一个:在routes.py文件中,创建一个名为includeme的函数(是的,它实际上必须命名为 this),它接受一个配置器对象作为参数。

# 在 routes.py 中

定义包含(配置):

"""在应用程序中包含这些路由。"""

:将config.add_route方法调用从__init__.py移到includeme函数中:

定义包含(配置):

"""在应用程序中包含这些路由。"""

config.add_route('你好', '/')

:提醒配置器您需要将此routes.py文件作为其配置的一部分。因为它与__init__.py位于同一目录中,所以您可以将此文件的导入路径指定为.routes

# 在 __init__.py

从 pyramid.config 导入配置器

def main(全局_config,**设置):

"""返回 Pyramid WSGI 应用程序。"""

配置\u003d配置器(设置\u003d设置)

config.include('.routes')

config.scan()

返回 config.make_wsgi_app()

连接数据库

与 Flask 一样,您需要通过连接数据库来持久化数据。 Pyramid 将直接利用SQLAlchemy,而不是使用专门定制的包。

首先把容易的部分排除在外。psycopg2sqlalchemy需要与 Postgres 数据库通信并管理模型,因此将它们添加到setup.py

# 在 setup.py 中

需要 \u003d [

'金字塔',

'金字塔-ipython',

“女服务员”,

'sqlalchemy',

'psycopg2'

]

# 等等等等其他代码

现在,您已经决定如何包含数据库的 URL。这里没有错误的答案;您所做的将取决于您正在构建的应用程序以及您的代码库需要的公开程度。

第一个选项将通过将数据库 URL 硬编码到config.ini文件中,将尽可能多的配置保存在一个位置。一个缺点是这会给具有公共代码库的应用程序带来安全风险。任何可以查看代码库的人都可以看到完整的数据库 URL,包括用户名、密码、数据库名称和端口。另一个是可维护性;如果您需要更改环境或应用程序的数据库位置,则必须直接修改config.ini文件。要么这样,要么您必须为每个新环境维护一个配置文件,这增加了应用程序中断和错误的可能性。 如果您选择此选项,请修改[app:main]标题下的config.ini文件以包含此键值对:

sqlalchemy.url = postgres://localhost:5432/pyramid_todo

第二个选项指定创建Configurator时数据库 URL 的位置,指向一个环境变量,其值可以根据您工作的环境进行设置。一个缺点是您进一步拆分了配置,其中一些位于config.ini文件中,而一些则直接位于 Python 代码库中。另一个缺点是,当您需要在应用程序的其他任何地方(例如,在数据库管理脚本中)使用数据库 URL 时,您必须在第二个引用中编写对同一环境变量的引用(或在一个地方设置变量并从该位置导入)。 如果您选择此选项,请添加以下内容:

# 在 __init__.py

进口我们

从 pyramid.config 导入配置器

SQLALCHEMY_URL \u003d os.environ.get('DATABASE_URL', '')

def main(全局_config,**设置):

"""返回 Pyramid WSGI 应用程序。"""

settings['sqlalchemy.url'] \u003d SQLALCHEMY_URL # <-- 重要!

配置\u003d配置器(设置\u003d设置)

config.include('.routes')

config.scan()

返回 config.make_wsgi_app()

定义对象

好的,现在你有了一个数据库。现在你需要TaskUser对象。

因为它直接使用 SQLAlchemy,Pyramid 在构建对象的方式上与 Flash 有所不同。首先,您要构造的每个对象都必须继承自 SQLAlchemy 的声明性基类。它将跟踪从它继承的所有内容,从而实现更简单的数据库管理。

# 在models.py中

从 sqlalchemy.ext.declarative 导入声明性_base

基\u003d声明_base()

类任务(基础):

经过

类用户(基础):

经过

列、这些列的数据类型和模型关系将以与 Flask 相同的方式声明,尽管它们将直接从 SQLAlchemy 导入,而不是一些预先构造的db对象。其他一切都是一样的。

# 在models.py中

从日期时间导入日期时间

导入机密

从 sqlalchemy 导入(

列、Unicode、整数、日期时间、布尔值、关系

)

从 sqlalchemy.ext.declarative 导入声明性_base

基\u003d声明_base()

类任务(基础):

"""待办事项列表的任务。"""

id \u003d 列(整数,主要_key\u003dTrue)

名称\u003d列(Unicode,可为空\u003d假)

注意 \u003d 列(Unicode)

创建_日期\u003d列(日期时间,可为空\u003d假)

到期\日期 \u003d 列(日期时间)

完成\u003d列(布尔值,默认\u003d假)

用户_id \u003d列(整数,ForeignKey('user.id'),可为空\u003d假)

用户\u003d关系(“用户”,返回_populates\u003d“任务”)

def __init__(self, *args, **kwargs):

"""在施工时,设置创建日期。"""

super().__init__(*args, **kwargs)

self.creation_date \u003d datetime.now()

类用户(基础):

"""拥有任务的用户对象。"""

id \u003d 列(整数,主要_key\u003dTrue)

用户名\u003d列(Unicode,可为空\u003d假)

电子邮件\u003d列(Unicode,可为空\u003d假)

密码\u003d列(Unicode,可为空\u003d假)

日期_加入\u003d列(日期时间,可为空\u003d假)

令牌\u003d列(Unicode,可为空\u003d假)

任务\u003d关系(“任务”,返回_populates\u003d"用户")

def __init__(self, *args, **kwargs):

"""在施工时,设置创建日期。"""

super().__init__(*args, **kwargs)

self.date_joined \u003d datetime.now()

self.token \u003d secrets.token_urlsafe(64)

请注意,models.py的任何地方都没有config.include行,因为它不是必需的。仅当需要更改应用程序配置的某些部分时才需要config.include行。这只创建了两个对象,继承自 SQLAlchemy 给我们的一些Base类。

初始化数据库

现在模型已经完成,您可以编写一个脚本来与数据库对话并初始化数据库。在scripts目录下,创建两个文件:__init__.pyinitializedb.py。第一种就是简单的把scripts目录转成Python包。第二个是数据库管理所需的脚本。

initializedb.py需要一个函数来在数据库中建立必要的表。与 Flask 一样,此脚本必须知道Base对象,其元数据跟踪从它继承的每个类。需要数据库 URL 来指向和修改其表。

因此,此数据库初始化脚本将起作用:

# 初始化b.py

从 sqlalchemy 导入引擎_from_config

从待办事项导入 SQLALCHEMY_URL

从 todo.models 导入基础

定义主():

设置 \u003d {'sqlalchemy.url': SQLALCHEMY_URL}

引擎\u003d引擎_from_config(设置,前缀\u003d'sqlalchemy。')

if bool(os.environ.get('DEBUG', '')):

Base.metadata.drop_all(engine)

Base.metadata.create_all(engine)

**重要提示:**这仅在您将数据库 URL 作为环境变量包含在todo/__init__.py(上面的第二个选项)中时才有效。如果数据库 URL 存储在配置文件中,则必须包含几行才能读取该文件。它看起来像这样:

# 备用初始化b.py

从pyramid.paster 导入get_appsettings

从 pyramid.scripts.common 导入解析_vars

从 sqlalchemy 导入引擎_from_config

导入系统

从 todo.models 导入基础

定义主():

配置_uri \u003d sys.argv[1]

选项\u003d解析_vars(sys.argv[2:])

设置\u003d获取_appsettings(配置_uri,选项\u003d选项)

引擎\u003d引擎_from_config(设置,前缀\u003d'sqlalchemy。')

if bool(os.environ.get('DEBUG', '')):

Base.metadata.drop_all(engine)

Base.metadata.create_all(engine)

无论哪种方式,在setup.py中,添加一个将访问并运行此函数的控制台脚本。

# setup.py 底部

设置(

# ... 其他的东西

入口_points\u003d{

'paste.app_factory': [

'main u003d todo:main',

],

'控制台_脚本':\ [

'initdb u003d todo.scripts.initializedb:main',

],

}

)

安装此软件包后,您将可以访问一个名为initdb的新控制台脚本,该脚本将在您的数据库中构建表。如果数据库 URL 存储在配置文件中,则在调用命令时必须包含该文件的路径。它看起来像$ initdb /path/to/config.ini

处理请求和数据库

好的,这就是它变得有点深的地方。让我们谈谈交易。抽象意义上的“事务”是对现有数据库所做的任何更改。与 Flask 一样,事务在提交时才会持久化。如果进行了尚未提交的更改,并且您不希望发生这些更改(可能在此过程中引发了错误),您可以回滚事务并中止这些更改。

在 Python 中,事务包允许您将事务作为对象进行交互,这可以将多个更改汇总到一个提交中。transaction提供了事务管理器,它为应用程序提供了一种直接的、线程感知的方式来处理事务,因此您只需要考虑要更改的内容。pyramid_tm包将从transaction获取事务管理器,并以适合 Pyramid 请求-响应周期的方式将其连接起来,将事务管理器附加到每个传入请求。

通常,当访问到视图的路由映射并调用视图函数时,使用 Pyramid 填充request对象。 每个视图函数都将具有 a request object 一起使用。 但是,Pyramid 允许您修改其配置以将您可能需要的任何内容添加到request对象。您可以使用您将添加到request的事务管理器为每个请求创建一个会话并将该会话添加到请求中。

是的,为什么这很重要?

通过将 transaction-managed session 附加到request对象,当视图完成对请求的处理时,对数据库会话所做的任何更改都将被提交,而无需您显式提交**。**这是所有这些概念在代码中的样子.

# __init__.py

进口我们

从 pyramid.config 导入配置器

从 sqlalchemy 导入引擎_from_config

从 sqlalchemy.orm 导入 sessionmaker

导入 zope.sqlalchemy

SQLALCHEMY_URL \u003d os.environ.get('DATABASE_URL', '')

def get_session_factory(引擎):

"""返回数据库会话对象的生成器。"""

工厂 \u003d sessionmaker()

factory.configure(绑定\u003d引擎)

返厂

def get_tm_session(session_factory, transaction_manager):

"""建立一个会话并将其注册为事务管理的会话。"""

dbsession \u003d session_factory()

zope.sqlalchemy.register(dbsession, transaction_manager\u003dtransaction_manager)

返回数据库会话

def main(全局_config,**设置):

"""返回 Pyramid WSGI 应用程序。"""

设置['sqlalchemy.url'] \u003d SQLALCHEMY_URL

设置['tm.manager_hook'] \u003d'金字塔_tm.explicit_manager'

配置\u003d配置器(设置\u003d设置)

config.include('.routes')

config.include('金字塔_tm')

session_factory \u003d get_session_factory(engine_from_config(settings, prefix\u003d'sqlalchemy.'))

config.registry['dbsession_factory'] \u003d session_factory

config.add_request_method(

lambda 请求:get_tm_session(session_factory, request.tm),

'dbsession',

物化\u003d真

)

config.scan()

返回 config.make_wsgi_app()

这看起来很多,但它只是做了上面解释的事情,另外它为request对象添加了一个名为request.dbsession的属性。

这里包含了一些新的包,所以用这些包更新setup.py

# 在 setup.py 中

需要 \u003d [

'金字塔',

'金字塔-ipython',

“女服务员”,

'sqlalchemy',

'psycopg2',

'金字塔_tm',

'交易',

'zope.sqlalchemy'

]

# 等等等等其他东西

重游路线和风景

您需要创建一些真实的视图来处理数据库中的数据以及映射到它们的路由。

从路线开始。您创建了routes.py文件来处理您的路线,但除了基本的/路线之外没有做太多事情。让我们解决这个问题。

# 路线.py

定义包含(配置):

config.add_route('info', '/api/v1/')

config.add_route('注册', '/api/v1/accounts')

config.add_route('profile_detail', '/api/v1/accounts/{username}')

config.add_route('login', '/api/v1/accounts/login')

config.add_route('注销', '/api/v1/accounts/logout')

config.add_route('tasks', '/api/v1/accounts/{username}/tasks')

config.add_route('task_detail', '/api/v1/accounts/{username}/tasks/{id}')

现在,它不仅有像/api/v1/accounts这样的静态 URL,而且它可以处理一些像/api/v1/accounts/{username}/tasks/{id}这样的变量 URL,其中 URL 中的任何变量都将被花括号括起来。

要创建视图以在应用程序中创建单个任务(如在 Flash 示例中),您可以使用@view_config装饰器来确保它只接收传入的POST请求并检查 Pyramid 如何处理来自客户端的数据。

看一下代码,然后看看它与 Flask 的版本有何不同。

# 在views.py中

从日期时间导入日期时间

从 pyramid.view 导入视图_config

从 todo.models 导入任务,用户

INCOMING_DATE_FMT \u003d '%d/%m/%Y %H:%M:%S'

@view_config(route_name\u003d"tasks", request_method\u003d"POST", renderer\u003d'json')

def 创建_task(请求):

"""为一个用户创建一个任务。"""

响应 \u003d request.response

response.headers.extend({'Content-Type': 'application/json'})

user \u003d request.dbsession.query(User).filter_by(username\u003drequest.matchdict['username']).first()

如果用户:

到期\日期\u003d request.json['到期\日期']

任务\u003d任务(

name\u003drequest.json['name'],

note\u003drequest.json['note'],

due_date\u003ddatetime.strptime(due_date, INCOMING_DATE_FMT) if due_date else None,

完成\u003d布尔(request.json['完成']),

用户_id\u003duser.id

)

request.dbsession.add(任务)

response.status_code \u003d 201

返回 {'msg': '已发布'}

首先,请注意@view_config装饰器,您希望此视图处理的唯一请求类型是“POST”请求。如果要指定一种类型的请求或一组请求,请提供注明请求的字符串或此类字符串的元组/列表。

响应 \u003d request.response

response.headers.extend({'Content-Type': 'application/json'})

# ...其他代码...

response.status_code \u003d 201

发送给客户端的HTTP响应是基于request.response生成的。通常,您不必担心该对象。它只会产生格式正确的 HTTP 响应,而您永远不会知道其中的区别。但是,因为您想做一些特定的事情,例如修改响应的状态代码和标头,所以您需要访问该响应及其方法/属性。

与 Flask 不同,您不需要仅仅因为路由 URL 中有变量就修改视图函数参数列表。相反,只要变量存在于路由 URL 中,它就会被收集在requestmatchdict属性中。它将作为键值对存在,其中键将是变量(例如,“用户名”),值将是路由中指定的任何值(例如,“bobdobson”)。无论通过路由 URL 传入什么值,它都会在matchdict中始终显示为字符串。因此,当您想从传入的请求 URL 中提取用户名时,请使用request.matchdict['username']访问它

user = request.dbsession.query(User).filter_by(username=request.matchdict['username']).first()

直接使用sqlalchemy时查询对象与flask-sqlalchemy包所允许的有很大不同。回想一下,当您使用flask-sqlalchemy构建模型时,模型继承自db.Model对象。db对象_已经包含到数据库的连接_,因此该连接可以执行像User.query.all()这样的简单操作。

这个简单的界面在这里不存在,因为 Pyramid 应用程序中的模型继承自Base,它是从declarative_base()生成的,直接来自sqlalchemy包。它对将要访问的数据库没有直接的认识。这种意识通过应用程序的中央配置作为dbsession属性附加到request对象。这是上面的代码:

config.add_request_method(

lambda 请求:get_tm_session(session_factory, request.tm),

'dbsession',

物化\u003d真

)

话虽如此,无论何时你想查询或修改数据库,你都必须工作 throughrequest.dbsession。在这种情况下,您想通过使用用户名作为标识符来查询特定用户的“用户”表。因此,User对象作为参数提供给.query方法,然后从那里完成正常的 SQLAlchemy 操作。

这种查询数据库的方式的一个有趣之处在于,您可以查询的不仅仅是一个对象或一种类型对象的列表。您可以查询:

  • 对象属性本身,例如,request.dbsession.query(User.username)将查询用户名

  • 对象属性的元组,例如request.dbsession.query(User.username, User.date_joined)

  • 多个对象的元组,例如request.dbsession.query(User, Task)

与传入请求一起发送的数据将在request.json字典中找到。

最后一个主要区别是,由于将会话活动的提交附加到 Pyramid 的请求-响应周期所需的所有机制,您不必在视图结束时调用request.dbsession.commit()。这很方便,但是要注意一件事。如果您想编辑数据库中预先存在的对象,而不是新添加到数据库,则不能使用request.dbsession.commit()。 Pyramid 会抛出一个错误,类似于“事务管理器正在处理提交行为,所以你不能自己调用它”。而且,如果您不执行类似于提交更改的操作,那么您的更改将不会生效。

这里的解决方案是使用request.dbsession.flush().flush()的工作是向数据库发出信号,表明已经进行了一些更改并且需要包含在下一次提交中。

规划未来

至此,您已经设置了 Pyramid 的大部分重要部分,类似于您在第一部分中使用 Flask 构建的内容。应用程序中还有更多内容,但大部分内容都是在这里处理的。其他视图函数将遵循类似的格式,当然,总是存在安全问题(Pyramid 已内置!)。

我在 Pyramid 应用程序的设置中看到的主要区别之一是它的配置步骤比 Flask 更密集。我分解了这些配置步骤,以更多地解释构建 Pyramid 应用程序时发生的事情。但是,自开始编程以来,表现得好像我就知道这一切是不诚实的。我对 Pyramid 框架的第一次体验是使用 Pyramid 1.7 和它的pcreate脚手架系统,它构建了大部分必要的配置,所以你需要做的就是考虑你想要构建的功能。

从 Pyramid 1.8 开始,pcreate已被弃用,取而代之的是cookiecutter,它实际上做了同样的事情。不同之处在于它由其他人维护,并且不仅仅是 Pyramid 项目的 cookiecutter 模板。既然我们已经了解了 Pyramid 项目的组件,当一个 cookiecutter 模板可用时,我永远不会再支持从头开始构建 Pyramid 项目。如果没有必要,为什么还要努力工作?事实上,pyramid-cookiecutter-alchemy模板将完成我在此处编写的大部分内容(以及更多内容)。它其实和我第一次学习 Pyramid 时使用的pcreate脚手架很相似。

在PyCon Cleveland 2018 了解更多 Python.

Logo

Python社区为您提供最前沿的新闻资讯和知识内容

更多推荐