Python Pyramid 简明教程

Python Pyramid - Package Structure

Cookiecutter 实用工具会自动在同名的父项目文件夹内创建一个包文件夹。包文件夹包括以下文件和子文件夹。

init.py

一个文件夹需要 init.py 文件,才能被视为一个 Python 包。 testproj 包也有这个文件,它本质上为 Pyramid WSGI 应用程序项目声明了 development.ini 以将其用作入口点。

main() 函数返回应用程序对象。它通过包括在运行 cookiecutter 时选择的模板库,包括 routes 模块,并通过扫描现有包来将视图添加到配置器,配置应用程序注册表。以下 Python 代码作为 init.py 文件自动生成。

from pyramid.config import Configurator
def main(global_config, **settings):
   """ This function returns a Pyramid WSGI application.
   """
   with Configurator(settings=settings) as config:
      config.include('pyramid_jinja2')
      config.include('.routes')
      config.include('.models')
      config.scan()
   return config.make_wsgi_app()

routes.py

Cookiecutter 实用工具会自动生成一个 Python 脚本,它有一个名为 includeme() 的函数。它添加一个静态路由和指向 '/' URL 模式的主页路由。

def includeme(config):
   config.add_static_view('static', 'static', cache_max_age=3600)
   config.add_route('home', '/')

这些路由通过上面介绍的 init.py 文件中的 main() 函数添加到应用程序配置。

Views Package

项目包(在我们的例子中为 testproj *package) contains this views subpackage - a folder containing a blank *init.py ,一个名为 default.py 的 Python 模块,其中包含名为 my_view() 的视图函数定义。)它将项目名称作为上下文发送到预构建模板 mytemplate.jinja2

from pyramid.view import view_config
from pyramid.response import Response
from sqlalchemy.exc import SQLAlchemyError
from .. import models

@view_config(route_name='home', renderer='testproj:templates/mytemplate.jinja2')
def my_view(request):
   try:
      query = request.dbsession.query(models.MyModel)
      one = query.filter(models.MyModel.name == 'one').one()
   except SQLAlchemyError:
      return Response(db_err_msg, content_type='text/plain', status=500)
   return {'one': one, 'project': 'testproj'}

db_err_msg = """\
Pyramid is having a problem using your SQL database.
....
"""

default.py 脚本还导入了模型子包中 mymodel 的定义。此视图包还在 notfound.py 文件中定义了 notfound 视图。

from pyramid.view import notfound_view_config
@notfound_view_config(renderer='testproj:templates/404.jinja2')
def notfound_view(request):
   request.response.status = 404
   return {}

Static Folder

testproj 包文件夹下的此文件夹包含 Pyramid logo 文件和针对主页的 theme.CSS。

Templates Folder

我们知道,Web 模板需要存储在 templates 文件夹中。此子文件夹包含 jinja2 模板。我们有一个名为 layout.jinja2 的基本模板, mytemplate.jinja2 继承了它,然后由 my_view() 视图函数渲染。

{% extends "layout.jinja2" %}

{% block content %}
<div class="content">
   <h1><span class="font-semi-bold">Pyramid</span> <span class="smaller">Starter project</span></h1>
   <p class="lead">Welcome to <span class="font-normal">{{project}}</span>, a Pyramid application generated by<br><span class="font-normal">Cookiecutter</span>.</p>
</div>
{% endblock content %}

Models Package

tesptproj 包文件夹下的此子包包含 mymodel.py ,其中具有名为 MyModel 的 SQLAlchemy 模型的定义。

from sqlalchemy import (
   Column,
   Index,
   Integer,
   Text,
)

from .meta import Base
class MyModel(Base):
   __tablename__ = 'models'
   id = Column(Integer, primary_key=True)
   name = Column(Text)
   value = Column(Integer)
Index('my_index', MyModel.name, unique=True, mysql_length=255)

meta.py 在 SQLAlchemy 中声明了一个 Declarative Base 类对象。

from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.schema import MetaData

NAMING_CONVENTION = {
   "ix": "ix_%(column_0_label)s",
   "uq": "uq_%(table_name)s_%(column_0_name)s",
   "ck": "ck_%(table_name)s_%(constraint_name)s",
   "fk": "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s",
   "pk": "pk_%(table_name)s"
}
metadata = MetaData(naming_convention=NAMING_CONVENTION)
Base = declarative_base(metadata=metadata)