Web Pecan 入门(一)

欢迎使用 Pecan,这是一个受 CherryPy,TurboGears 和 Pylons 启发的精益的(lean) Python Web 框架。Pecan 最初由开发者 ShootQPictage 工作时创建。

Pecan 的创建是为了填补 Python Web 框架世界中的空白:一个非常轻巧的框架,它提供了对象分派样式路由(object-dispatch style routing)。Pecan 并非旨在成为“全栈”框架,因此不提供对会话(sessions)或数据库之类的现成支持。相反地 Pecan 专注于 HTTP 本身。

尽管它很轻巧,但 Pecan 确实提供了广泛的功能集,可用于构建基于 HTTP 的应用程序,包括:

  • Object-dispatch for easy routing
  • Full support for REST-style controllers
  • Extensible security framework
  • Extensible template language support
  • Extensible JSON support
  • Easy Python-based configuration

虽然 Pecan 不提供对现成的会话或数据库的支持,但包含了一些教程,可以将它们集成到几行代码中。

1 Hello World

让我们用 Pecan 创建一个小样本项目。

1.1 基本应用程序模板

Pecan 包含用于启动新项目的基本模板(template)。在您的 Shell 中,键入:

$ pecan create test_project

显示:

本示例使用 test_project 作为项目名称,但是您可以将其替换为所需的任何有效 Python 软件包名称。

进入您新创建的项目目录:

$ cd test_project

您需要以“develop” 模式部署它,以便它在 sys.path 上可用,但仍可以直接从其源代码分发对其进行编辑:

$ python setup.py develop

您的新项目包含以下文件:

文件和目录的数量可能会根据 Pecan 的版本而有所不同,但是上述结构应该使您对预期的想法有所了解。

我们来看一下模板创建的文件。

  1. public:所有的静态文件(如 CSS,JavaScript 和图像)都位于此处。Pecan 随附了一个简单的文件服务器,该服务器在您开发时会提供这些静态文件。

Pecan 的应用程序结构通常遵循 MVC 模式。test_project 下的目录包含您的模型(model),控制器(controllers)和模板(templates)。

2 test_project/controllers:控制器文件的容器目录。

  1. test_project/templates:所有的模板都放在这里。
  2. test_project/model:模型文件的容器。

最后,一个用于存放单元和集成测试的目录:

  1. test_project/tests:针对您的应用程序的所有测试。

test_project/app.py 文件控制将如何创建 Pecan 应用程序。该文件必须包含一个 setup_app 函数,该函数返回 WSGI 应用程序对象。通常,除非您需要以无法使用 config 来完成的方式自定义应用程序,否则无需修改基本应用程序模板提供的 app.py 文件。请参阅基于 Python 的配置

为了避免不必要的依赖关系并尽可能保持灵活性,Pecan 不会强加任何数据库或 ORM(Object Relational Mapper,对象关系映射器)。如果您的项目将与数据库交互,则可以将代码添加到 model/__init__.py,以从配置文件中加载数据库绑定并定义 tables 和 ORM。

1.2 运行应用程序

基础项目模板使用在 config.py 中运行 Pecan 应用程序所需的基本设置创建配置文件。该文件包括运行服务器的主机和端口,控制器和模板在磁盘上的存储位置以及包含任何静态文件的目录的名称。

如果您只是运行 pecan serve,则将 config.py 作为配置文件传递,它将启动开发服务器并为应用程序提供服务:

显示:

配置文件的位置和参数本身非常灵活:您可以将绝对或相对路径传递给该文件。

1.3 基于 Python 的配置

为了易于使用,Pecan 配置文件是纯 Python,甚至会另存为 .py 文件。这是默认(生成的)配置文件的外观:

# Server Specific Configurations
server = {
    'port': '8080',
    'host': '0.0.0.0'
}

# Pecan Application Configurations
app = {
    'root': 'test_project.controllers.root.RootController',
    'modules': ['test_project'],
    'static_root': '%(confdir)s/public',
    'template_path': '%(confdir)s/test_project/templates',
    'debug': True,
    'errors': {
        404: '/error/404',
        '__force_dict__': True
    }
}

logging = {
    'root': {'level': 'INFO', 'handlers': ['console']},
    'loggers': {
        'test_project': {'level': 'DEBUG', 'handlers': ['console'], 'propagate': False},
        'pecan': {'level': 'DEBUG', 'handlers': ['console'], 'propagate': False},
        'py.warnings': {'handlers': ['console']},
        '__force_dict__': True
    },
    'handlers': {
        'console': {
            'level': 'DEBUG',
            'class': 'logging.StreamHandler',
            'formatter': 'color'
        }
    },
    'formatters': {
        'simple': {
            'format': ('%(asctime)s %(levelname)-5.5s [%(name)s]'
                       '[%(threadName)s] %(message)s')
        },
        'color': {
            '()': 'pecan.log.ColorFormatter',
            'format': ('%(asctime)s [%(padded_color_levelname)s] [%(name)s]'
                       '[%(threadName)s] %(message)s'),
            '__force_dict__': True
        }
    }
}

# Custom Configurations must be in Python dictionary format::
#
# foo = {'bar':'baz'}
#
# All configurations are accessible at::
# pecan.conf

您还可以将自己的配置添加为 Python 字典。

这里有很多要讨论的内容,因此我们将在下一章(配置 Pecan 应用程序)中回到配置文件。

1.4 应用的 Root

Root Controller 是您应用程序的入口点。您可以认为它类似于应用程序的根 URL 路径(在我们的示例中为 http://localhost:8080/)。

在项目模板(test_project.controllers.root.RootController)中的看起来如下:

from pecan import expose
from webob.exc import status_map


class RootController(object):

    @expose(generic=True, template='index.html')
    def index(self):
        return dict()

    @index.when(method='POST')
    def index_post(self, q):
        redirect(f'https://pecan.readthedocs.io/en/latest/search.html?q={q}')

    @expose('error.html')
    def error(self, status):
        try:
            status = int(status)
        except ValueError:
            status = 0
        message = getattr(status_map.get(status), 'explanation', '')
        return dict(status=status, message=message)

如果需要,您可以指定其他类和方法,但现在,让我们逐个控制器检查示例项目:

@expose(generic=True, template='index.html')
def index(self):
    return dict()

通过应用程序根目录(http://127.0.0.1:8080/) 上的 expose() 装饰器(依次使用 index.html 模板)将 index() 方法标记为可公开使用,因此任何 HTTP GET 到达应用程序根目录(/)的路径将被路由到此方法。

注意 index() 方法返回一个 Python 字典。该字典用作将指定模板(index.html)呈现为 HTML 的命名空间,并且是将数据从控制器传递到模板的主要机制。

@index.when(method='POST')
def index_post(self, q):
    redirect(f'https://pecan.readthedocs.io/en/latest/search.html?q={q}')

index_post() 方法接收一个 HTTP POST 参数(q)。由于 @index.when() 的参数方法已设置为 'POST',因此到应用程序根目录的所有 HTTP POST(在示例项目中为表单提交)都将路由到该方法。

@expose('error.html')
def error(self, status):
    try:
        status = int(status)
    except ValueError:
        status = 0
    message = getattr(status_map.get(status), 'explanation', '')
    return dict(status=status, message=message)

最后,我们有 error() 方法,该方法允许应用程序显示某些 HTTP 错误(404等)的自定义页面。

1.5 为应用程序运行测试

应用程序附带一些示例测试,您可以运行,替换和添加这些测试。要运行它们:

$ python setup.py test -q
running test
running egg_info
writing requirements to sam.egg-info/requires.txt
writing sam.egg-info/PKG-INFO
writing top-level names to sam.egg-info/top_level.txt
writing dependency_links to sam.egg-info/dependency_links.txt
reading manifest file 'sam.egg-info/SOURCES.txt'
reading manifest template 'MANIFEST.in'
writing manifest file 'sam.egg-info/SOURCES.txt'
running build_ext
....
----------------------------------------------------------------------
Ran 4 tests in 0.009s

OK

测试本身可以在项目的 tests 模块中找到。

1.6 部署到 Web 服务器

准备部署新的 Pecan 应用程序了吗?看看在开发中部署 Pecan

推荐阅读更多精彩内容