Python Pyramid 简明教程
Python Pyramid - Package Structure
Cookiecutter 实用工具会自动在同名的父项目文件夹内创建一个包文件夹。包文件夹包括以下文件和子文件夹。
The Cookiecutter utility automatically creates a package folder inside the parent project folder of the same name. The package folder consists of the following files and subfolders.
init.py
一个文件夹需要 init.py 文件,才能被视为一个 Python 包。 testproj 包也有这个文件,它本质上为 Pyramid WSGI 应用程序项目声明了 development.ini 以将其用作入口点。
A folder needs init.py file for it to be treated as a Python package. The testproj package also has this file, which essentially declares the Pyramid WSGI application project for the development.ini to use it as the entry point.
main() 函数返回应用程序对象。它通过包括在运行 cookiecutter 时选择的模板库,包括 routes 模块,并通过扫描现有包来将视图添加到配置器,配置应用程序注册表。以下 Python 代码作为 init.py 文件自动生成。
The application object is returned by the main() function. It configures the application registry by including the template library chosen at the time of running cookiecutter, including the routes module and adding the views to the configurator by scanning the existing package. Following Python code is auto generated as init.py file.
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 模式的主页路由。
The Cookiecutter utility automatically generates a Python script having a function called includeme(). It adds a static route and a home route pointing to '/' URL pattern.
def includeme(config):
config.add_static_view('static', 'static', cache_max_age=3600)
config.add_route('home', '/')
这些路由通过上面介绍的 init.py 文件中的 main() 函数添加到应用程序配置。
These routes are added to the application configuration by the main() function in init.py file explained above.
Views Package
项目包(在我们的例子中为 testproj *package) contains this views subpackage - a folder containing a blank *init.py ,一个名为 default.py 的 Python 模块,其中包含名为 my_view() 的视图函数定义。)它将项目名称作为上下文发送到预构建模板 mytemplate.jinja2
The project package (in our case testproj *package) contains this views subpackage - a folder containing a blank *init.py, a Python module called default.py that contains definition a view function named my_view(). It sends the name of the project as a context to a pre-built template 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 视图。
The default.py scripts also imports definition of mymodel in models subpackage. This views package also defines a notfound view in notfound.py file.
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。
This folder under the testproj package folder contains Pyramid logo files and theme.CSS for the homepage.
Templates Folder
我们知道,Web 模板需要存储在 templates 文件夹中。此子文件夹包含 jinja2 模板。我们有一个名为 layout.jinja2 的基本模板, mytemplate.jinja2 继承了它,然后由 my_view() 视图函数渲染。
We know that the web templates need to be stored in templates folder. This subfolder contains jinja2 templates. Here we have a base template named as layout.jinja2 and it is inherited by mytemplate.jinja2 to be rendered by my_view() view function.
{% 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 模型的定义。
This subpackage under the tesptproj package folder holds mymodel.py that has the definition of SQLAlchemy model named as MyModel.
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 类对象。
The meta.py declares an object of Declarative Base class in SQLAlchemy.
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)