├── .gitignore
├── .travis.yml
├── CONTRIBUTORS.txt
├── README.rst
├── contributing.md
├── docs
├── Makefile
├── auth
│ ├── auth_tutorial.rst
│ ├── basic.rst
│ ├── custom.rst
│ ├── enterprise.rst
│ ├── index.rst
│ ├── jwt_auth.rst
│ ├── open_id_auth.rst
│ ├── user_object.rst
│ └── wiki2_auth.rst
├── automating_development_process
│ ├── index.rst
│ ├── part1.rst
│ ├── part2.rst
│ └── part3.rst
├── conf.py
├── configuration
│ ├── django_settings.rst
│ ├── index.rst
│ └── whirlwind_tour.rst
├── database
│ ├── couchdb.rst
│ ├── index.rst
│ ├── mongodb.rst
│ └── sqlalchemy.rst
├── debugging
│ ├── debugging_pyramid.rst
│ ├── index.rst
│ ├── pydev.rst
│ └── using_pdb.rst
├── deployment
│ ├── apache.rst
│ ├── asgi.rst
│ ├── aws_via_eb.rst
│ ├── deployment.rst
│ ├── dotcloud.rst
│ ├── expresscloud.rst
│ ├── forked_threaded_servers.rst
│ ├── gae.rst
│ ├── gae_buildout.rst
│ ├── gae_flex_datastore.rst
│ ├── gevent.rst
│ ├── gunicorn.rst
│ ├── heroku.rst
│ ├── index.rst
│ ├── nginx.rst
│ ├── uwsgi.rst
│ ├── uwsgi_cookiecutter_1_nginx.rst
│ ├── uwsgi_cookiecutter_2_emperor.rst
│ ├── uwsgi_nginx_systemd.rst
│ └── windows.rst
├── development_tools
│ ├── index.rst
│ ├── pycharm.rst
│ └── pycharm_images
│ │ ├── create_new_project.png
│ │ ├── create_setup.png
│ │ ├── create_virtual_environment.png
│ │ ├── edit_run_debug_configurations.png
│ │ ├── install_package.png
│ │ ├── install_package_pyramid.png
│ │ ├── install_package_setuptools.png
│ │ ├── python_interpreters_1.png
│ │ ├── python_interpreters_2.png
│ │ ├── run_configuration.png
│ │ └── start_up_screen.png
├── forms
│ ├── file_uploads.rst
│ └── index.rst
├── index.rst
├── links.rst
├── logging
│ ├── index.rst
│ └── sqlalchemy_logger.rst
├── misc
│ ├── events.rst
│ ├── index.rst
│ ├── interfaces.rst
│ └── videos.rst
├── porting
│ ├── index.rst
│ ├── legacy.rst
│ └── wsgi.rst
├── pylons
│ ├── auth.rst
│ ├── code
│ │ ├── alchemy_main.py
│ │ ├── model_development.ini
│ │ ├── models.py
│ │ ├── pyramid_handlers.py
│ │ └── starter_main.py
│ ├── deployment.rst
│ ├── examples.rst
│ ├── exceptions.rst
│ ├── index.rst
│ ├── ini_file.rst
│ ├── intro.rst
│ ├── launch.rst
│ ├── main.rst
│ ├── migrate.rst
│ ├── models.rst
│ ├── other.rst
│ ├── request.rst
│ ├── sessions.rst
│ ├── static.rst
│ ├── templates.rst
│ └── views.rst
├── routing
│ ├── combining.rst
│ ├── index.rst
│ ├── traversal_in_views.rst
│ └── traversal_sqlalchemy.rst
├── sample_applications
│ ├── index.rst
│ ├── single_file_tasks.png
│ ├── single_file_tasks.rst
│ └── single_file_tasks_src
│ │ ├── .gitignore
│ │ ├── Makefile
│ │ ├── buildout.cfg
│ │ ├── schema.sql
│ │ ├── static
│ │ └── style.css
│ │ ├── tasks.py
│ │ └── templates
│ │ ├── layout.mako
│ │ ├── list.mako
│ │ ├── new.mako
│ │ └── notfound.mako
├── static_assets
│ ├── bundling-static-assets.rst
│ ├── bundling
│ │ ├── .gitignore
│ │ ├── bundling_example
│ │ │ ├── .coveragerc
│ │ │ ├── .gitignore
│ │ │ ├── CHANGES.txt
│ │ │ ├── MANIFEST.in
│ │ │ ├── README.txt
│ │ │ ├── bundling_example
│ │ │ │ ├── __init__.py
│ │ │ │ ├── routes.py
│ │ │ │ ├── scripts
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ └── build_static_assets.py
│ │ │ │ ├── static
│ │ │ │ │ ├── pyramid-16x16.png
│ │ │ │ │ ├── pyramid.png
│ │ │ │ │ └── theme.css
│ │ │ │ ├── templates
│ │ │ │ │ ├── 404.jinja2
│ │ │ │ │ ├── layout.jinja2
│ │ │ │ │ └── mytemplate.jinja2
│ │ │ │ ├── tests.py
│ │ │ │ └── views
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── default.py
│ │ │ │ │ └── notfound.py
│ │ │ ├── development.ini
│ │ │ ├── production.ini
│ │ │ ├── pytest.ini
│ │ │ └── setup.py
│ │ └── frontend
│ │ │ ├── package.json
│ │ │ ├── src
│ │ │ ├── index.js
│ │ │ ├── sass.js
│ │ │ └── sass
│ │ │ │ └── main.scss
│ │ │ └── webpack.config.js
│ ├── index.rst
│ ├── serving-files.rst
│ └── uploading-files.rst
├── templates
│ ├── chameleon_i18n.rst
│ ├── customrenderers.rst
│ ├── customrendererxlsx.rst
│ ├── index.rst
│ ├── mako_i18n.rst
│ └── templates.rst
├── testing
│ ├── index.rst
│ └── testing_post_curl.rst
├── todo.rst
├── traversal_tutorial
│ ├── addcontent.rst
│ ├── addcontent
│ │ ├── development.ini
│ │ ├── setup.py
│ │ └── tutorial
│ │ │ ├── __init__.py
│ │ │ ├── resources.py
│ │ │ ├── templates
│ │ │ ├── addform.jinja2
│ │ │ ├── breadcrumbs.jinja2
│ │ │ ├── contents.jinja2
│ │ │ ├── document.jinja2
│ │ │ ├── folder.jinja2
│ │ │ ├── header.jinja2
│ │ │ ├── layout.jinja2
│ │ │ └── root.jinja2
│ │ │ ├── tests.py
│ │ │ └── views.py
│ ├── hierarchy.rst
│ ├── hierarchy
│ │ ├── development.ini
│ │ ├── setup.py
│ │ └── tutorial
│ │ │ ├── __init__.py
│ │ │ ├── resources.py
│ │ │ ├── templates
│ │ │ ├── breadcrumbs.jinja2
│ │ │ ├── header.jinja2
│ │ │ ├── hello.jinja2
│ │ │ ├── home.jinja2
│ │ │ └── layout.jinja2
│ │ │ ├── tests.py
│ │ │ └── views.py
│ ├── index.rst
│ ├── layout.rst
│ ├── layout
│ │ ├── development.ini
│ │ ├── setup.py
│ │ └── tutorial
│ │ │ ├── __init__.py
│ │ │ ├── templates
│ │ │ ├── breadcrumbs.jinja2
│ │ │ ├── header.jinja2
│ │ │ ├── layout.jinja2
│ │ │ └── site.jinja2
│ │ │ ├── tests.py
│ │ │ └── views.py
│ ├── requirements.rst
│ ├── siteroot.rst
│ ├── siteroot
│ │ ├── development.ini
│ │ ├── setup.py
│ │ └── tutorial
│ │ │ ├── __init__.py
│ │ │ ├── resources.py
│ │ │ ├── templates
│ │ │ ├── breadcrumbs.jinja2
│ │ │ ├── header.jinja2
│ │ │ ├── hello.jinja2
│ │ │ ├── home.jinja2
│ │ │ └── layout.jinja2
│ │ │ ├── tests.py
│ │ │ └── views.py
│ ├── sqladdcontent.rst
│ ├── sqladdcontent
│ │ ├── development.ini
│ │ ├── setup.py
│ │ └── tutorial
│ │ │ ├── __init__.py
│ │ │ ├── initialize_db.py
│ │ │ ├── models.py
│ │ │ ├── sqltraversal.py
│ │ │ ├── templates
│ │ │ ├── addform.jinja2
│ │ │ ├── breadcrumbs.jinja2
│ │ │ ├── contents.jinja2
│ │ │ ├── document.jinja2
│ │ │ ├── folder.jinja2
│ │ │ ├── header.jinja2
│ │ │ ├── layout.jinja2
│ │ │ └── root.jinja2
│ │ │ └── views.py
│ ├── sqlauthentication
│ │ ├── development.ini
│ │ ├── setup.py
│ │ └── tutorial
│ │ │ ├── __init__.py
│ │ │ ├── initialize_db.py
│ │ │ ├── models.py
│ │ │ ├── security.py
│ │ │ ├── templates
│ │ │ ├── addform.jinja2
│ │ │ ├── breadcrumbs.jinja2
│ │ │ ├── contents.jinja2
│ │ │ ├── document.jinja2
│ │ │ ├── folder.jinja2
│ │ │ ├── header.jinja2
│ │ │ ├── layout.jinja2
│ │ │ ├── login.jinja2
│ │ │ └── root.jinja2
│ │ │ └── views.py
│ ├── sqlroot.rst
│ ├── sqlroot
│ │ ├── development.ini
│ │ ├── setup.py
│ │ └── tutorial
│ │ │ ├── __init__.py
│ │ │ ├── initialize_db.py
│ │ │ ├── models.py
│ │ │ ├── templates
│ │ │ ├── breadcrumbs.jinja2
│ │ │ ├── header.jinja2
│ │ │ ├── hello.jinja2
│ │ │ ├── home.jinja2
│ │ │ └── layout.jinja2
│ │ │ └── views.py
│ ├── typeviews.rst
│ ├── typeviews
│ │ ├── development.ini
│ │ ├── setup.py
│ │ └── tutorial
│ │ │ ├── __init__.py
│ │ │ ├── resources.py
│ │ │ ├── templates
│ │ │ ├── breadcrumbs.jinja2
│ │ │ ├── contents.jinja2
│ │ │ ├── document.jinja2
│ │ │ ├── folder.jinja2
│ │ │ ├── header.jinja2
│ │ │ ├── layout.jinja2
│ │ │ └── root.jinja2
│ │ │ ├── tests.py
│ │ │ └── views.py
│ ├── zodb.rst
│ └── zodb
│ │ ├── development.ini
│ │ ├── setup.py
│ │ └── tutorial
│ │ ├── __init__.py
│ │ ├── resources.py
│ │ ├── templates
│ │ ├── addform.jinja2
│ │ ├── breadcrumbs.jinja2
│ │ ├── contents.jinja2
│ │ ├── document.jinja2
│ │ ├── folder.jinja2
│ │ ├── header.jinja2
│ │ ├── layout.jinja2
│ │ └── root.jinja2
│ │ └── views.py
└── views
│ ├── chaining_decorators.rst
│ ├── conditional_http.rst
│ ├── index.rst
│ └── params_mapper.rst
├── rtd.txt
├── setup.cfg
├── setup.py
└── tox.ini
/.gitignore:
--------------------------------------------------------------------------------
1 | *.egg
2 | *.egg-info
3 | .eggs/
4 | *.pyc
5 | *.swp
6 | build/
7 | dist/
8 | docs/_build
9 | env/
10 | .DS_Store
11 |
12 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | # Wire up travis
2 | language: python
3 | sudo: false
4 |
5 | matrix:
6 | include:
7 | - python: 3.6
8 | env: TOXENV=docs
9 |
10 | install:
11 | - travis_retry pip install tox
12 |
13 | script:
14 | - travis_retry tox
15 |
16 | cache:
17 | directories:
18 | - $HOME/.cache/pip
19 |
20 | notifications:
21 | email:
22 | - pyramid-checkins@lists.repoze.org
23 | irc:
24 | channels:
25 | - "chat.freenode.net#pyramid"
26 |
--------------------------------------------------------------------------------
/README.rst:
--------------------------------------------------------------------------------
1 | Pyramid Community Cookbook
2 | ==========================
3 |
4 | The Pyramid Community Cookbook presents topical, practical "recipes" of using
5 | Pyramid. It supplements the `main Pyramid documentation
6 | `_.
7 |
8 | To contribute your recipe to the Pyramid Community Cookbook, read `Contributing
9 | `_.
10 |
--------------------------------------------------------------------------------
/docs/auth/auth_tutorial.rst:
--------------------------------------------------------------------------------
1 | Pyramid Auth Demo
2 | =================
3 |
4 | See Michael Merickel's article `Pyramid Auth Demo
5 | `_ with its `code on
6 | GitHub `_ for a demonstration
7 | of Pyramid authentication and authorization.
--------------------------------------------------------------------------------
/docs/auth/basic.rst:
--------------------------------------------------------------------------------
1 | HTTP Basic Authentication Policy
2 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 |
4 | To adopt basic HTTP authentication, you can use Pyramid's built-in authentication policy, :class:`pyramid.authentication.BasicAuthAuthenticationPolicy`.
5 |
6 | This is a complete working example with very simple authentication and authorization::
7 |
8 | from pyramid.authentication import BasicAuthAuthenticationPolicy
9 | from pyramid.authorization import ACLAuthorizationPolicy
10 | from pyramid.config import Configurator
11 | from pyramid.httpexceptions import HTTPForbidden
12 | from pyramid.httpexceptions import HTTPUnauthorized
13 | from pyramid.security import ALL_PERMISSIONS
14 | from pyramid.security import Allow
15 | from pyramid.security import Authenticated
16 | from pyramid.security import forget
17 | from pyramid.view import forbidden_view_config
18 | from pyramid.view import view_config
19 |
20 | @view_config(route_name='home', renderer='json', permission='view')
21 | def home_view(request):
22 | return {
23 | 'page': 'home',
24 | 'userid': request.authenticated_userid,
25 | 'principals': request.effective_principals,
26 | 'context_type': str(type(request.context)),
27 | }
28 |
29 | @forbidden_view_config()
30 | def forbidden_view(request):
31 | if request.authenticated_userid is None:
32 | response = HTTPUnauthorized()
33 | response.headers.update(forget(request))
34 |
35 | # user is logged in but doesn't have permissions, reject wholesale
36 | else:
37 | response = HTTPForbidden()
38 | return response
39 |
40 | def check_credentials(username, password, request):
41 | if username == 'admin' and password == 'admin':
42 | # an empty list is enough to indicate logged-in... watch how this
43 | # affects the principals returned in the home view if you want to
44 | # expand ACLs later
45 | return []
46 |
47 | class Root:
48 | # dead simple, give everyone who is logged in any permission
49 | # (see the home_view for an example permission)
50 | __acl__ = (
51 | (Allow, Authenticated, ALL_PERMISSIONS),
52 | )
53 |
54 | def main(global_conf, **settings):
55 | config = Configurator(settings=settings)
56 |
57 | authn_policy = BasicAuthAuthenticationPolicy(check_credentials)
58 | config.set_authentication_policy(authn_policy)
59 | config.set_authorization_policy(ACLAuthorizationPolicy())
60 | config.set_root_factory(lambda request: Root())
61 |
62 | config.add_route('home', '/')
63 |
64 | config.scan(__name__)
65 | return config.make_wsgi_app()
66 |
67 | if __name__ == '__main__':
68 | from waitress import serve
69 | app = main({})
70 | serve(app, listen='localhost:8000')
71 |
--------------------------------------------------------------------------------
/docs/auth/custom.rst:
--------------------------------------------------------------------------------
1 | Custom Authentication Policy
2 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 |
4 | Here is an example of a custom AuthenticationPolicy, based off of
5 | the native ``AuthTktAuthenticationPolicy``, but with added groups support.
6 | This example implies you have a ``user`` attribute on your request
7 | (see :ref:`user object`) and that the ``user`` should have a
8 | ``groups`` relation on it::
9 |
10 | from pyramid.authentication import AuthTktCookieHelper
11 | from pyramid.security import Everyone, Authenticated
12 |
13 | class MyAuthenticationPolicy(object):
14 |
15 | def __init__(self, settings):
16 | self.cookie = AuthTktCookieHelper(
17 | settings.get('auth.secret'),
18 | cookie_name=settings.get('auth.token') or 'auth_tkt',
19 | secure=asbool(settings.get('auth.secure')),
20 | timeout=asint(settings.get('auth.timeout')),
21 | reissue_time=asint(settings.get('auth.reissue_time')),
22 | max_age=asint(settings.get('auth.max_age')),
23 | )
24 |
25 | def remember(self, request, principal, **kw):
26 | return self.cookie.remember(request, principal, **kw)
27 |
28 | def forget(self, request):
29 | return self.cookie.forget(request)
30 |
31 | def unauthenticated_userid(self, request):
32 | result = self.cookie.identify(request)
33 | if result:
34 | return result['userid']
35 |
36 | def authenticated_userid(self, request):
37 | if request.user:
38 | return request.user.id
39 |
40 | def effective_principals(self, request):
41 | principals = [Everyone]
42 | user = request.user
43 | if user:
44 | principals += [Authenticated, 'u:%s' % user.id]
45 | principals.extend(('g:%s' % g.name for g in user.groups))
46 | return principals
47 |
48 |
49 | Thanks to `raydeo` for this one.
50 |
--------------------------------------------------------------------------------
/docs/auth/enterprise.rst:
--------------------------------------------------------------------------------
1 | Integration with Enterprise Systems
2 | ===================================
3 |
4 | When using Pyramid within an "enterprise" (or an intranet), it is often desirable to
5 | integrate with existing authentication and authorization (entitlement) systems.
6 | For example, in Microsoft Network environments, the user database is typically
7 | maintained in Active Directory. At present, there is no ready-to-use recipe, but we
8 | are listing places that may be worth looking at for ideas when developing one:
9 |
10 | Authentication
11 | --------------
12 |
13 | * `adpasswd project on pypi `_
14 | * `Tim Golden's Active Directory Cookbook `_
15 | * `python-ad `_
16 | * `python-ldap.org `_
17 | * `python-ntmlm `_
18 | * `Blog post on managing AD from Python in Linux `_
19 |
20 | Authorization
21 | -------------
22 |
23 | * `Microsoft Authorization Manager `_
24 | * `Fundamentals of WCF Security `_
25 | * `Calling WCF Services from C++ using gSOAP `_
26 |
27 |
--------------------------------------------------------------------------------
/docs/auth/index.rst:
--------------------------------------------------------------------------------
1 | Authentication and Authorization
2 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 | .. toctree::
4 | :maxdepth: 1
5 |
6 | basic
7 | custom
8 | jwt_auth
9 | user_object
10 | wiki2_auth
11 | auth_tutorial
12 | open_id_auth
13 | enterprise
14 |
15 | For basic information on authentication and authorization, see the
16 | `security `_
17 | section of the Pyramid documentation.
18 |
19 |
--------------------------------------------------------------------------------
/docs/auth/open_id_auth.rst:
--------------------------------------------------------------------------------
1 | Google, Facebook, Twitter, and any OpenID Authentication
2 | ========================================================
3 |
4 | See `Wayne Witzel III's blog post
5 | `_
6 | about using Velruse and Pyramid together to do Google OAuth authentication.
7 |
8 | See Matthew Housden and Chris Davies apex project for any basic and
9 | openid authentication such as Google, Facebook, Twitter and more at
10 | https://github.com/cd34/apex.
11 |
12 |
--------------------------------------------------------------------------------
/docs/automating_development_process/index.rst:
--------------------------------------------------------------------------------
1 | Automating the Development Process
2 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 |
4 | .. toctree::
5 | :maxdepth: 2
6 |
7 | part1
8 | part2
9 | part3
10 |
11 | Based on `Davide Moro `_ articles (how to
12 | integrate the Yeoman workflow with Pyramid):
13 |
14 | - `Pyramid starter seed template powered by Yeoman (part 1) `_
15 | - `Pyramid starter seed template powered by Yeoman (part 2) `_
16 | - `Pyramid starter seed template powered by Yeoman (part 3) `_
17 |
--------------------------------------------------------------------------------
/docs/automating_development_process/part1.rst:
--------------------------------------------------------------------------------
1 | What is pyramid_starter_seed
2 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 |
4 | This tutorial should help you to start developing with the Pyramid web
5 | framework using a very minimal starter seed project based on:
6 |
7 | - a Pyramid's `pcreate -t starter` project
8 | - a `Yeoman `_ `generator-webapp` project
9 |
10 | You can find the Pyramid starter seed code here on Github:
11 |
12 | - `pyramid_starter_seed `_
13 |
14 | Thanks to Yeoman you can improve your developer experience when you are in
15 | **development** or **production** mode thanks to:
16 |
17 | - Javascript testing setup
18 | - Javascript code linting
19 | - Javascript/CSS concat and minification
20 | - image assets optimization
21 | - html template minification
22 | - switch to CDN versions of you vendor plugins in production mode
23 | - uncss
24 | - much more (you can add features adding new Grunt tasks)
25 |
26 | We will see later how you can clone `pyramid_starter_seed` from github, add
27 | new features (eg: authentication, SQLAlchemy support, user models, a json
28 | REST API, add a modern Javascript framework as AngularJS, etc) and then
29 | launch a console script that helps you to rename the entire project with
30 | your more opinionated modifications, for example
31 | `pyramid_yourawesomeproduct`.
32 |
33 | Based on `Davide Moro `_ articles (how to
34 | integrate the Yeoman workflow with Pyramid):
35 |
36 | - `Pyramid starter seed template powered by Yeoman (part 1) `_
37 | - `Pyramid starter seed template powered by Yeoman (part 2) `_
38 | - `Pyramid starter seed template powered by Yeoman (part 3) `_
39 |
--------------------------------------------------------------------------------
/docs/automating_development_process/part2.rst:
--------------------------------------------------------------------------------
1 | Prerequisites
2 | %%%%%%%%%%%%%
3 |
4 | If you want to play with *pyramid_starter_seed* you'll need to install
5 | `NodeJS `_ and, obviously, Python.
6 | Once installed Python and Pyramid, you'll have to clone the
7 | pyramid_starter_seed repository from github and initialize the Yeoman stuff.
8 |
9 | Python and Pyramid
10 | ==================
11 |
12 | pyramid_starter_seed was tested with Python 2.7.
13 | Create an isolated Python environment as explained in the official Pyramid
14 | documentation and install Pyramid.
15 |
16 | Official Pyramid installation documentation
17 |
18 | - https://docs.pylonsproject.org/projects/pyramid/en/latest/narr/install.html#installing-chapter
19 |
20 | NodeJS
21 | ======
22 |
23 | You won't use NodeJS at all in your code, you just need to install
24 | development dependencies required by the Yeoman tools.
25 |
26 | Once installed NodeJS (if you want to easily install different versions
27 | on your system and manage them you can use the NodeJS Version Manager
28 | utility: `NVM `_), you need to
29 | enable the following tools:
30 |
31 | .. code-block:: bash
32 |
33 | $ npm install -g bower
34 | $ npm install -g grunt-cli
35 | $ npm install -g karma
36 |
37 | Tested with NodeJS version 0.10.31.
38 |
39 | How to install pyramid_starter_seed
40 | ===================================
41 |
42 | Clone *pyramid_starter_seed* from github:
43 |
44 | .. code-block:: bash
45 |
46 | $ git clone git@github.com:davidemoro/pyramid_starter_seed.git
47 | $ cd pyramid_starter_seed
48 | $ YOUR_VIRTUALENV_PYTHON_PATH/bin/python setup.py develop
49 |
50 | Yeoman initialization
51 | ---------------------
52 |
53 | Go to the folder where it lives our Yeoman project and initialize it.
54 |
55 | These are the standard commands (but, wait a moment, see the "Notes and
56 | known issues" subsection):
57 |
58 | .. code-block:: bash
59 |
60 | $ cd pyramid_starter_seed/webapp
61 | $ bower install
62 | $ npm install
63 |
64 | Known issues
65 | ------------
66 |
67 | You'll need to perform these additional steps in order to get a working
68 | environment (the generator-webapp's version used by pyramid_starter_seed
69 | has a couple of known issues).
70 |
71 | Avoid imagemin errors on build:
72 |
73 | .. code-block:: bash
74 |
75 | $ npm cache clean
76 | $ npm install grunt-contrib-imagemin
77 |
78 | Avoid Mocha/PhantomJS issue (see
79 | `issues #446 `_):
80 |
81 | .. code-block:: bash
82 |
83 | $ cd test
84 | $ bower install
85 |
86 | Build
87 | -----
88 |
89 | Run:
90 |
91 | .. code-block:: bash
92 |
93 | $ grunt build
94 |
95 | Run pyramid_starter_seed
96 | ========================
97 |
98 | Now can choose to run Pyramid in development or production mode.
99 |
100 | Go to the root of your project directory, where the files `development.ini`
101 | and `production.ini` are located.
102 |
103 | .. code-block:: bash
104 |
105 | cd ../../..
106 |
107 | Just type:
108 |
109 | .. code-block:: bash
110 |
111 | $ YOUR_VIRTUALENV_PYTHON_PATH/bin/pserve development.ini
112 |
113 | or:
114 |
115 | .. code-block:: bash
116 |
117 | $ YOUR_VIRTUALENV_PYTHON_PATH/bin/pserve production.ini
118 |
119 |
--------------------------------------------------------------------------------
/docs/configuration/django_settings.rst:
--------------------------------------------------------------------------------
1 | Django-Style "settings.py" Configuration
2 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 |
4 | If you enjoy accessing global configuration via import statements ala
5 | Django's ``settings.py``, you can do something similar in Pyramid.
6 |
7 | - Create a ``settings.py`` file in your application's package (for example,
8 | if your application is named "myapp", put it in the filesystem directory
9 | named ``myapp``; the one with an ``__init__.py`` in it.
10 |
11 | - Add values to it at its top level.
12 |
13 | For example::
14 |
15 | # settings.py
16 | import pytz
17 |
18 | timezone = pytz('US/Eastern')
19 |
20 | Then simply import the module into your application::
21 |
22 | from myapp import settings
23 |
24 | def myview(request):
25 | timezone = settings.timezone
26 | return Response(timezone.zone)
27 |
28 | This is all you really need to do if you just want some global configuration
29 | values for your application.
30 |
31 | However, more frequently, values in your ``settings.py`` file need to be
32 | conditionalized based on deployment settings. For example, the timezone
33 | above is different between development and deployment. In order to
34 | conditionalize the values in your ``settings.py`` you can use *other* values
35 | from the Pyramid ``development.ini`` or ``production.ini``. To do so,
36 | your ``settings.py`` might instead do this::
37 |
38 | import os
39 |
40 | ini = os.environ['PYRAMID_SETTINGS']
41 | config_file, section_name = ini.split('#', 1)
42 |
43 | from paste.deploy.loadwsgi import appconfig
44 | config = appconfig('config:%s' % config_file, section_name)
45 |
46 | import pytz
47 |
48 | timezone = pytz.timezone(config['timezone'])
49 |
50 | The value of ``config`` in the above snippet will be a dictionary
51 | representing your application's ``development.ini`` configuration section.
52 | For example, for the above code to work, you'll need to add a ``timezone``
53 | key/value pair to a section of your ``development.ini``::
54 |
55 | [app:myapp]
56 | use = egg:MyApp
57 | timezone = US/Eastern
58 |
59 | If your ``settings.py`` is written like this, before starting Pyramid, ensure
60 | you have an OS environment value (akin to Django's ``DJANGO_SETTINGS``) in
61 | this format::
62 |
63 | export PYRAMID_SETTINGS=/place/to/development.ini#myapp
64 |
65 | ``/place/to/development.ini`` is the full path to the ini file. ``myapp`` is
66 | the section name in the config file that represents your app
67 | (e.g. ``[app:myapp]``). In the above example, your application will refuse
68 | to start without this environment variable being present.
69 |
--------------------------------------------------------------------------------
/docs/configuration/index.rst:
--------------------------------------------------------------------------------
1 | Configuration
2 | %%%%%%%%%%%%%
3 |
4 | .. toctree::
5 | :maxdepth: 2
6 |
7 | whirlwind_tour
8 | django_settings
9 |
10 | For more information on configuration see the following sections of the Pyramid documentation:
11 |
12 | - `basic configuration `_
13 | - `advanced configuration `_
14 | - `configuration introspection `_
15 | - `extending configuration `_
16 | - `PasteDeploy configuration `_
17 |
--------------------------------------------------------------------------------
/docs/database/index.rst:
--------------------------------------------------------------------------------
1 | Databases
2 | %%%%%%%%%
3 |
4 | .. toctree::
5 | :maxdepth: 2
6 |
7 | sqlalchemy
8 | couchdb
9 | mongodb
10 |
--------------------------------------------------------------------------------
/docs/database/mongodb.rst:
--------------------------------------------------------------------------------
1 | MongoDB and Pyramid
2 | ===================
3 |
4 | Basics
5 | ------
6 |
7 | If you want to use MongoDB (via PyMongo and perhaps GridFS) via Pyramid, you
8 | can use the following pattern to make your Mongo database available as a
9 | request attribute.
10 |
11 | First add the MongoDB URI to your ``development.ini`` file. (Note: ``user``, ``password`` and ``port`` are not required.)
12 |
13 | .. code-block:: ini
14 | :linenos:
15 |
16 | [app:myapp]
17 | # ... other settings ...
18 | mongo_uri = mongodb://user:password@host:port/database
19 |
20 | Then in your ``__init__.py``, set things up such that the database is
21 | attached to each new request::
22 |
23 | from pyramid.config import Configurator
24 |
25 | try:
26 | # for python 2
27 | from urlparse import urlparse
28 | except ImportError:
29 | # for python 3
30 | from urllib.parse import urlparse
31 |
32 | from gridfs import GridFS
33 | from pymongo import MongoClient
34 |
35 |
36 | def main(global_config, **settings):
37 | """ This function returns a Pyramid WSGI application.
38 | """
39 | config = Configurator(settings=settings)
40 | config.add_static_view('static', 'static', cache_max_age=3600)
41 |
42 | db_url = urlparse(settings['mongo_uri'])
43 | config.registry.db = MongoClient(
44 | host=db_url.hostname,
45 | port=db_url.port,
46 | )
47 |
48 | def add_db(request):
49 | db = config.registry.db[db_url.path[1:]]
50 | if db_url.username and db_url.password:
51 | db.authenticate(db_url.username, db_url.password)
52 | return db
53 |
54 | def add_fs(request):
55 | return GridFS(request.db)
56 |
57 | config.add_request_method(add_db, 'db', reify=True)
58 | config.add_request_method(add_fs, 'fs', reify=True)
59 |
60 | config.add_route('dashboard', '/')
61 | # other routes and more config...
62 | config.scan()
63 | return config.make_wsgi_app()
64 |
65 |
66 | .. note::
67 |
68 | ``Configurator.add_request_method`` has been available since Pyramid 1.4.
69 | You can use ``Configurator.set_request_property`` for Pyramid 1.3.
70 |
71 | At this point, in view code, you can use ``request.db`` as the PyMongo database
72 | connection. For example::
73 |
74 | @view_config(route_name='dashboard',
75 | renderer="myapp:templates/dashboard.pt")
76 | def dashboard(request):
77 | vendors = request.db['vendors'].find()
78 | return {'vendors':vendors}
79 |
80 |
81 | Scaffolds
82 | ---------
83 |
84 | Niall O'Higgins provides a `pyramid_mongodb
85 | `_ scaffold for Pyramid that
86 | provides an easy way to get started with Pyramid and MongoDB.
87 |
88 |
89 | Video
90 | -----
91 |
92 | Niall O'Higgins provides a presentation he gave at a Mongo conference in San
93 | Francisco at https://www.mongodb.com/presentations/weather-century
94 |
95 |
96 | Other Information
97 | -----------------
98 |
99 | - Pyramid, Aket and MongoDB:
100 | http://niallohiggins.com/2011/05/18/mongodb-python-pyramid-akhet/
101 |
--------------------------------------------------------------------------------
/docs/debugging/index.rst:
--------------------------------------------------------------------------------
1 | Debugging
2 | %%%%%%%%%
3 |
4 | .. toctree::
5 | :maxdepth: 2
6 |
7 | using_pdb
8 | debugging_pyramid
9 | pydev
10 |
11 |
--------------------------------------------------------------------------------
/docs/debugging/using_pdb.rst:
--------------------------------------------------------------------------------
1 | Using PDB to Debug Your Application
2 | +++++++++++++++++++++++++++++++++++
3 |
4 | ``pdb`` is an interactive tool that comes with Python, which allows you to
5 | break your program at an arbitrary point, examine values, and step through
6 | code. It's often much more useful than print statements or logging
7 | statements to examine program state. You can place a ``pdb.set_trace()``
8 | statement in your Pyramid application at a place where you'd like to examine
9 | program state. When you issue a request to the application, and that point
10 | in your code is reached, you will be dropped into the ``pdb`` debugging
11 | console within the terminal that you used to start your application.
12 |
13 | There are lots of great resources that can help you learn PDB.
14 |
15 | - Doug Hellmann's PyMOTW blog entry entitled "pdb - Interactive Debugger" at
16 | https://pymotw.com/3/pdb/ is the canonical text resource to learning PDB.
17 |
18 | - The PyCon video presentation by Chris McDonough entitled "Introduction to
19 | PDB" at https://pyvideo.org/video/644/introduction-to-pdb is a good place to
20 | start learning PDB.
21 |
22 | - The video at https://pyvideo.org/pycon-us-2012/introduction-to-pdb.html shows you
23 | how to start how to start to using pdb. The video describes using ``pdb``
24 | in a command-line program.
25 |
--------------------------------------------------------------------------------
/docs/deployment/apache.rst:
--------------------------------------------------------------------------------
1 | Apache + mod_wsgi
2 | +++++++++++++++++
3 |
4 | `Pyramid mod_wsgi tutorial `_
5 |
--------------------------------------------------------------------------------
/docs/deployment/aws_via_eb.rst:
--------------------------------------------------------------------------------
1 | Amazon Web Services via Elastic Beanstalk
2 | +++++++++++++++++++++++++++++++++++++++++
3 |
4 | Dan Clark published two tutorials for deploying Pyramid applications on `Amazon Web Services (AWS) `_ via `Elastic Beanstalk `_.
5 |
6 | `How-to: Hello Pyramid on AWS `_ shows how to deploy the `Hello World application `_.
7 |
8 | `How-to: Pyramid Starter on AWS `_ shows how to deploy a project generated from the `pyramid-cookiecutter-starter `_.
9 |
--------------------------------------------------------------------------------
/docs/deployment/deployment.rst:
--------------------------------------------------------------------------------
1 | Deploying Your Pyramid Application
2 | ----------------------------------
3 |
4 | So you've written a sweet application and you want to deploy it outside of
5 | your local machine. We're not going to cover caching here, but suffice it to
6 | say that there are a lot of things to consider when optimizing your pyramid
7 | application.
8 |
9 | At a high level, you need to expose a server on ports 80 (HTTP) and 443
10 | (HTTPS). Underneath this layer, however, is
11 | a plethora of different configurations that can be used to get a request
12 | from a client, into your application, and return the response.
13 |
14 | ::
15 |
16 | Client <---> WSGI Server <---> Your Application
17 |
18 | Due to the beauty of standards, many different configurations can be used to
19 | generate this basic setup, injecting caching layers, load balancers, and so on into
20 | the basic workflow.
21 |
22 | Disclaimer
23 | ++++++++++
24 |
25 | It's important to note that the setups discussed here are meant to give some
26 | direction to newer users. Deployment is *almost always* highly dependent on
27 | the application's specific purposes. These setups have been used for many
28 | different projects in production with much success, but never verbatim.
29 |
30 | What is WSGI?
31 | +++++++++++++
32 |
33 | WSGI is a `Python standard `_
34 | dictating the interface between a server and an
35 | application. The entry point to your pyramid application is an object
36 | implementing the WSGI interface. Thus, your application can be served by any
37 | server supporting WSGI.
38 |
39 | There are many different servers implementing the WSGI standard in existence.
40 | A short list includes:
41 |
42 | + ``waitress``
43 |
44 | + ``paste.httpserver``
45 |
46 | + ``CherryPy``
47 |
48 | + ``uWSGI``
49 |
50 | + ``gevent``
51 |
52 | + ``mod_wsgi``
53 |
54 | For more information on WSGI, see the `WSGI home `_.
55 |
56 | Special Considerations
57 | ++++++++++++++++++++++
58 |
59 | Certain environments and web servers require special considerations when
60 | deploying your Pyramid application due to implementation details of Python, the
61 | web server, or popular packages.
62 |
63 | Forked and threaded servers share some common gotchas and solutions.
64 |
65 | :doc:`forked_threaded_servers`
66 |
--------------------------------------------------------------------------------
/docs/deployment/expresscloud.rst:
--------------------------------------------------------------------------------
1 | OpenShift Express Cloud
2 | +++++++++++++++++++++++
3 |
4 | `This blog entry
5 | `_
6 | describes deploying a Pyramid application to RedHat's OpenShift Express Cloud
7 | platform.
8 |
9 | Luke Macken's `OpenShift Quickstarter
10 | `_ also provides an easy
11 | way to get started using OpenShift.
12 |
--------------------------------------------------------------------------------
/docs/deployment/gae.rst:
--------------------------------------------------------------------------------
1 | .. _appengine_tutorial:
2 |
3 | Google App Engine Standard and :app:`Pyramid`
4 | =============================================
5 |
6 | It is possible to run a :app:`Pyramid` application on `Google App Engine `_. This tutorial is written in terms of using the command line on a UNIX system. It should be possible to perform similar actions on a Windows system. This tutorial also assumes you've already installed and created a :app:`Pyramid` application, and that you have a Google App Engine account.
7 |
8 | Setup
9 | -----
10 |
11 | First we'll need to create a few files so that App Engine can communicate with our project properly.
12 |
13 | Create the files with content as follows.
14 |
15 | #. ``requirements.txt``
16 |
17 | .. code-block:: text
18 |
19 | Pyramid
20 | waitress
21 | pyramid_debugtoolbar
22 | pyramid_chameleon
23 |
24 | #. ``main.py``
25 |
26 | .. code-block:: python
27 |
28 | from pyramid.paster import get_app, setup_logging
29 | ini_path = 'production.ini'
30 | setup_logging(ini_path)
31 | application = get_app(ini_path, 'main')
32 |
33 | #. ``appengine_config.py``
34 |
35 | .. code-block:: python
36 |
37 | from google.appengine.ext import vendor
38 | vendor.add('lib')
39 |
40 | #. ``app.yaml``
41 |
42 | .. code-block:: yaml
43 |
44 | application: application-id
45 | version: version
46 | runtime: python27
47 | api_version: 1
48 | threadsafe: false
49 |
50 | handlers:
51 | - url: /static
52 | static_dir: pyramid_project/static
53 | - url: /.*
54 | script: main.application
55 |
56 | Configure this file with the following values:
57 |
58 | * Replace "application-id" with your App Engine application's ID.
59 | * Replace "version" with the version you want to deploy.
60 | * Replace "pyramid_project" in the definition for ``static_dir`` with the parent directory name of your static assets. If your static assets are in the root directory, you can just put "static".
61 |
62 | For more details about ``app.yaml``, see `app.yaml Reference `_.
63 |
64 | #. Install dependencies.
65 |
66 | .. code-block:: bash
67 |
68 | $ pip install -t lib -r requirements.txt
69 |
70 |
71 | Running locally
72 | ---------------
73 |
74 | At this point you should have everything you need to run your Pyramid application locally using ``dev_appserver``. Assuming you have appengine in your ``$PATH``:
75 |
76 | .. code-block:: bash
77 |
78 | $ dev_appserver.py app.yaml
79 |
80 | And voilà! You should have a perfectly-running Pyramid application via Google App Engine on your local machine.
81 |
82 |
83 | Deploying
84 | ---------
85 |
86 | If you've successfully launched your application locally, deploy with a single command.
87 |
88 | .. code-block:: bash
89 |
90 | $ appcfg.py update app.yaml
91 |
92 | Your Pyramid application is now live to the world! You can access it by navigating to your domain name, by ".appspot.com", or if you've specified a version outside of your default then it would be ".appspot.com".
93 |
--------------------------------------------------------------------------------
/docs/deployment/gevent.rst:
--------------------------------------------------------------------------------
1 | gevent
2 | ++++++
3 |
4 | gevent + pyramid_socketio
5 | =========================
6 |
7 | Alexandre Bourget explains how he uses gevent + socketio to add functionality to a Pyramid application at https://pyvideo.org/pycon-ca-2012/gevent-socketio-cross-framework-real-time-web-li.html
8 |
9 | gevent + long polling
10 | =====================
11 |
12 | https://michael.merickel.org/2011/6/21/tictactoe-and-long-polling-with-pyramid/
13 |
14 | https://github.com/mmerickel/tictactoe
15 |
16 | For more information on gevent see the `gevent home page `_
17 |
--------------------------------------------------------------------------------
/docs/deployment/gunicorn.rst:
--------------------------------------------------------------------------------
1 | ********
2 | gunicorn
3 | ********
4 |
5 | The short story
6 | ===============
7 | Running your pyramid based application with gunicorn can be as easy as:
8 |
9 | .. code-block:: bash
10 |
11 | $ gunicorn --paste production.ini
12 |
13 |
14 | The long story
15 | ==============
16 | Similar to the ``pserve`` command that comes with Pyramid, gunicorn can also
17 | directly use your project's INI files, such as ``production.ini``, to launch
18 | your application. Just supply the ``--paste`` command line option together with
19 | the path of your configuration file to the ``gunicorn`` command, and it will
20 | try to load the app.
21 |
22 | As documented in the section `Paste Deployment
23 | `_, you
24 | may also add gunicorn specific settings to the ``[server:main]`` section of
25 | your INI file and continue using the ``pserve`` command.
26 |
27 | The following configuration will cause gunicorn to listen on a unix socket, use
28 | four workers, preload the application, output accesslog lines to stderr and use
29 | the debug loglevel.
30 |
31 | .. code-block:: ini
32 |
33 | [server:main]
34 | use = egg:gunicorn#main
35 | bind = unix:/var/run/app.sock
36 | workers = 4
37 | preload = true
38 | accesslog = -
39 | loglevel = debug
40 |
41 | For all configuration options that may be used, have a look at the `available
42 | settings `_.
43 |
44 | Keep in mind that settings defined within a gunicorn configuration file
45 | take precedence over the settings established within the INI file.
46 |
47 | For all of this to work, the Python interpreter used by gunicorn also needs to
48 | be able to load your application. In other words, gunicorn and your application
49 | need to be installed and used inside the same ``virtualenv``.
50 |
51 | Naturally, the ``paste`` option can also be combined with other gunicorn
52 | options that might be applicable for your deployment situation. Also you might
53 | want to put something like `nginx `_ in
54 | front of gunicorn and have gunicorn supervised by some process manager. Please
55 | have a look at the `gunicorn website `_ and the `gunicorn
56 | documentation on deployment `_
57 | for more information on those topics.
58 |
--------------------------------------------------------------------------------
/docs/deployment/index.rst:
--------------------------------------------------------------------------------
1 | Deployment
2 | ++++++++++
3 |
4 | Introduction
5 | ------------
6 |
7 | .. toctree::
8 | :maxdepth: 1
9 |
10 | deployment
11 |
12 |
13 | Web Servers
14 | -----------
15 |
16 | .. toctree::
17 | :maxdepth: 1
18 |
19 | apache
20 | asgi
21 | forked_threaded_servers
22 | gevent
23 | gunicorn
24 | nginx
25 | uwsgi
26 | uwsgi_cookiecutter_1_nginx
27 | uwsgi_cookiecutter_2_emperor
28 | uwsgi_nginx_systemd
29 |
30 |
31 | Cloud Providers
32 | ---------------
33 |
34 | .. toctree::
35 | :maxdepth: 1
36 |
37 | aws_via_eb
38 | dotcloud
39 | gae
40 | gae_buildout
41 | gae_flex_datastore
42 | heroku
43 | expresscloud
44 |
45 |
46 | Windows
47 | -------
48 |
49 | .. toctree::
50 | :maxdepth: 1
51 |
52 | windows
53 |
--------------------------------------------------------------------------------
/docs/deployment/uwsgi.rst:
--------------------------------------------------------------------------------
1 | uWSGI
2 | +++++
3 |
4 | This brief chapter covers how to configure a `uWSGI `_ server for Pyramid.
5 |
6 | Pyramid is a Paste-compatible web application framework. As such, you can use the uWSGI ``--paste`` option to conveniently deploy your application.
7 |
8 | For example, if you have a virtual environment in ``/opt/env`` containing a Pyramid application called ``wiki`` configured in ``/opt/env/wiki/development.ini``:
9 |
10 | .. code-block:: bash
11 |
12 | uwsgi --paste config:/opt/env/wiki/development.ini --socket :3031 -H /opt/env
13 |
14 | The example is modified from the `original example for Turbogears `_.
15 |
--------------------------------------------------------------------------------
/docs/development_tools/index.rst:
--------------------------------------------------------------------------------
1 | Development Tools
2 | %%%%%%%%%%%%%%%%%
3 |
4 | This section is a collection of development tools and tips, resource files, and
5 | other things that help make writing code in Python for Pyramid easier and more
6 | fun.
7 |
8 | .. toctree::
9 | :maxdepth: 2
10 |
11 | pycharm
12 |
--------------------------------------------------------------------------------
/docs/development_tools/pycharm_images/create_new_project.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pylons/pyramid_cookbook/35bbfad6637ea85adbf0e18d168b8ecc3d01707d/docs/development_tools/pycharm_images/create_new_project.png
--------------------------------------------------------------------------------
/docs/development_tools/pycharm_images/create_setup.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pylons/pyramid_cookbook/35bbfad6637ea85adbf0e18d168b8ecc3d01707d/docs/development_tools/pycharm_images/create_setup.png
--------------------------------------------------------------------------------
/docs/development_tools/pycharm_images/create_virtual_environment.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pylons/pyramid_cookbook/35bbfad6637ea85adbf0e18d168b8ecc3d01707d/docs/development_tools/pycharm_images/create_virtual_environment.png
--------------------------------------------------------------------------------
/docs/development_tools/pycharm_images/edit_run_debug_configurations.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pylons/pyramid_cookbook/35bbfad6637ea85adbf0e18d168b8ecc3d01707d/docs/development_tools/pycharm_images/edit_run_debug_configurations.png
--------------------------------------------------------------------------------
/docs/development_tools/pycharm_images/install_package.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pylons/pyramid_cookbook/35bbfad6637ea85adbf0e18d168b8ecc3d01707d/docs/development_tools/pycharm_images/install_package.png
--------------------------------------------------------------------------------
/docs/development_tools/pycharm_images/install_package_pyramid.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pylons/pyramid_cookbook/35bbfad6637ea85adbf0e18d168b8ecc3d01707d/docs/development_tools/pycharm_images/install_package_pyramid.png
--------------------------------------------------------------------------------
/docs/development_tools/pycharm_images/install_package_setuptools.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pylons/pyramid_cookbook/35bbfad6637ea85adbf0e18d168b8ecc3d01707d/docs/development_tools/pycharm_images/install_package_setuptools.png
--------------------------------------------------------------------------------
/docs/development_tools/pycharm_images/python_interpreters_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pylons/pyramid_cookbook/35bbfad6637ea85adbf0e18d168b8ecc3d01707d/docs/development_tools/pycharm_images/python_interpreters_1.png
--------------------------------------------------------------------------------
/docs/development_tools/pycharm_images/python_interpreters_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pylons/pyramid_cookbook/35bbfad6637ea85adbf0e18d168b8ecc3d01707d/docs/development_tools/pycharm_images/python_interpreters_2.png
--------------------------------------------------------------------------------
/docs/development_tools/pycharm_images/run_configuration.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pylons/pyramid_cookbook/35bbfad6637ea85adbf0e18d168b8ecc3d01707d/docs/development_tools/pycharm_images/run_configuration.png
--------------------------------------------------------------------------------
/docs/development_tools/pycharm_images/start_up_screen.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pylons/pyramid_cookbook/35bbfad6637ea85adbf0e18d168b8ecc3d01707d/docs/development_tools/pycharm_images/start_up_screen.png
--------------------------------------------------------------------------------
/docs/forms/file_uploads.rst:
--------------------------------------------------------------------------------
1 | File Uploads
2 | %%%%%%%%%%%%
3 |
4 | There are two parts necessary for handling file uploads. The first is to
5 | make sure you have a form that's been setup correctly to accept files. This
6 | means adding ``enctype`` attribute to your ``form`` element with the value of
7 | ``multipart/form-data``. A very simple example would be a form that accepts
8 | an mp3 file. Notice we've setup the form as previously explained and also
9 | added an ``input`` element of the ``file`` type.
10 |
11 | .. code-block:: html
12 | :linenos:
13 |
14 |
22 |
23 | The second part is handling the file upload in your view callable (above,
24 | assumed to answer on ``/store_mp3_view``). The uploaded file is added to the
25 | request object as a ``cgi.FieldStorage`` object accessible through the
26 | ``request.POST`` multidict. The two properties we're interested in are the
27 | ``file`` and ``filename`` and we'll use those to write the file to disk::
28 |
29 | import os
30 | import uuid
31 | import shutil
32 | from pyramid.response import Response
33 |
34 | def store_mp3_view(request):
35 | # ``filename`` contains the name of the file in string format.
36 | #
37 | # WARNING: this example does not deal with the fact that IE sends an
38 | # absolute file *path* as the filename. This example is naive; it
39 | # trusts user input.
40 |
41 | filename = request.POST['mp3'].filename
42 |
43 | # ``input_file`` contains the actual file data which needs to be
44 | # stored somewhere.
45 |
46 | input_file = request.POST['mp3'].file
47 |
48 | # Note that we are generating our own filename instead of trusting
49 | # the incoming filename since that might result in insecure paths.
50 | # Please note that in a real application you would not use /tmp,
51 | # and if you write to an untrusted location you will need to do
52 | # some extra work to prevent symlink attacks.
53 |
54 | file_path = os.path.join('/tmp', '%s.mp3' % uuid.uuid4())
55 |
56 | # We first write to a temporary file to prevent incomplete files from
57 | # being used.
58 |
59 | temp_file_path = file_path + '~'
60 |
61 | # Finally write the data to a temporary file
62 | input_file.seek(0)
63 | with open(temp_file_path, 'wb') as output_file:
64 | shutil.copyfileobj(input_file, output_file)
65 |
66 | # Now that we know the file has been fully saved to disk move it into place.
67 |
68 | os.rename(temp_file_path, file_path)
69 |
70 | return Response('OK')
71 |
--------------------------------------------------------------------------------
/docs/forms/index.rst:
--------------------------------------------------------------------------------
1 | .. _forms:
2 |
3 | Forms
4 | %%%%%
5 |
6 | Pyramid does not include a form library because there are several good ones on
7 | PyPI, but none that is obviously better than the others.
8 |
9 | Deform_ is a form library written for Pyramid, and maintained by the Pylons
10 | Project. It has a `demo `_.
11 |
12 | You can use WebHelpers and FormEncode in Pyramid just like in Pylons. Use
13 | pyramid_simpleform_ to organize your view code. (This replaces Pylons'
14 | @validate decorator, which has no equivalent in Pyramid.) FormEncode's
15 | documentation is a bit obtuse and sparse, but it's so widely flexible that you
16 | can do things in FormEncode that you can't in other libraries, and you can also
17 | use it for non-HTML validation; e.g., to validate the settings in the INI file.
18 |
19 | Some Pyramid users have had luck with WTForms, Formish, ToscaWidgets, etc.
20 |
21 | There are also form packages tied to database records, most notably
22 | FormAlchemy. These will publish a form to add/modify/delete records of a
23 | certain ORM class.
24 |
25 |
26 | Articles
27 | --------
28 |
29 | .. toctree::
30 |
31 | file_uploads
32 |
33 |
34 | .. include:: ../links.rst
35 |
--------------------------------------------------------------------------------
/docs/index.rst:
--------------------------------------------------------------------------------
1 | .. _pyramid-cookbook:
2 |
3 | Pyramid Community Cookbook
4 | ==========================
5 |
6 | The Pyramid Community Cookbook presents topical, practical "recipes" of using
7 | Pyramid. It supplements the :ref:`main documentation `.
8 |
9 | To contribute your recipe to the Pyramid Community Cookbook, read `Contributing
10 | `_.
11 |
12 | Table of contents
13 | -----------------
14 |
15 | .. toctree::
16 | :maxdepth: 2
17 |
18 | auth/index
19 | automating_development_process/index
20 | configuration/index
21 | database/index
22 | debugging/index
23 |
24 | .. toctree::
25 | :maxdepth: 3
26 |
27 | deployment/index
28 |
29 | .. toctree::
30 | :maxdepth: 2
31 |
32 | development_tools/index
33 | forms/index
34 | logging/index
35 | porting/index
36 | pylons/index
37 | routing/index
38 | sample_applications/index
39 | static_assets/index
40 | templates/index
41 | testing/index
42 | traversal_tutorial/index
43 | views/index
44 | misc/index
45 | todo
46 |
47 | :ref:`Pyramid Glossary `
48 |
49 | Indices and tables
50 | ==================
51 |
52 | * :ref:`genindex`
53 | * :ref:`search`
54 |
55 |
--------------------------------------------------------------------------------
/docs/links.rst:
--------------------------------------------------------------------------------
1 | ..
2 | This file contains external links referenced in one or more Cookbook
3 | articles.
4 |
5 | The Cookbook configuration has an "intersphinx inventory", which allows you
6 | to link to sections in the Pyramid manual and glossary without providing
7 | absolute URLs. To get a list of current reference names, download
8 | https://docs.pylonsproject.org/projects/pyramid/en/latest/objects.inv and
9 | uncompress it (GZIP format). It will be a text file with lines like this:
10 |
11 | response std:term -1 glossary.html#term-$ -
12 | mako_templates std:label -1 narr/templates.html#mako-templates Templating With Mako Templates
13 |
14 | Lines with "std:term" are glossary entries. You can put :term:`response` in
15 | your article and it will be rendered as a link to the glossary term. Lines
16 | with "std:label" are section targets. You can put :term:`mako_templates` in
17 | your article and it will be rendered as a link to that section in the
18 | Pyramid manual with the section title as the link text. Or you can override
19 | the link text with the Docutils text syntax: :ref:`Mako `.
20 |
21 | Note: this isn't working for me with multiword terms with spaces.
22 |
23 |
24 | .. _Pyramid manual: https://docs.pylonsproject.org/projects/pyramid/en/latest/
25 | .. _Tutorials: https://docs.pylonsproject.org/projects/pyramid/en/latest/#tutorials
26 | .. _Installing Pyramid: https://docs.pylonsproject.org/projects/pyramid/en/latest/narr/install.html
27 | .. _Creating a Pyramid Project: https://docs.pylonsproject.org/projects/pyramid/en/latest/narr/project.html
28 |
29 | .. _Akhet: https://docs.pylonsproject.org/projects/akhet/en/latest/
30 | .. _Beaker: https://beaker.readthedocs.io/en/latest/sessions.html
31 | .. _SQLAlchemy manual: http://docs.sqlalchemy.org/en/latest/
32 | .. _pyramid_handlers: https://docs.pylonsproject.org/projects/pyramid-handlers/en/latest/
33 | .. _pyramid_routehelper: https://github.com/Pylons/pyramid_routehelper/blob/master/pyramid_routehelper/__init__.py
34 |
35 | .. _Deform: https://docs.pylonsproject.org/projects/deform/en/latest/
36 | .. _pyramid_simpleform: https://pythonhosted.org/pyramid_simpleform/
37 |
38 | .. _Kotti: https://kotti.readthedocs.io/en/latest/
39 | .. _Ptah: https://ptahproject.readthedocs.io/en/latest/
40 | .. _Khufu: https://github.com/khufuproject
41 |
--------------------------------------------------------------------------------
/docs/logging/index.rst:
--------------------------------------------------------------------------------
1 | Logging
2 | %%%%%%%
3 |
4 | .. toctree::
5 | :maxdepth: 2
6 |
7 | sqlalchemy_logger
8 |
9 | For more information on logging, see the `Logging
10 | `_
11 | section of the Pyramid documentation.
12 |
--------------------------------------------------------------------------------
/docs/misc/events.rst:
--------------------------------------------------------------------------------
1 | Using Object Events in Pyramid
2 | ------------------------------
3 |
4 | .. warning:: This code works only in Pyramid 1.1a4+. It will also make your
5 | brain explode.
6 |
7 | Zope's Component Architecture supports the concept of "object events", which
8 | are events which call a subscriber with an context object *and* the event
9 | object.
10 |
11 | Here's an example of using an object event subscriber via the ``@subscriber``
12 | decorator::
13 |
14 | from zope.component.event import objectEventNotify
15 | from zope.component.interfaces import ObjectEvent
16 |
17 | from pyramid.events import subscriber
18 | from pyramid.view import view_config
19 |
20 | class ObjectThrownEvent(ObjectEvent):
21 | pass
22 |
23 | class Foo(object):
24 | pass
25 |
26 | @subscriber([Foo, ObjectThrownEvent])
27 | def objectevent_listener(object, event):
28 | print object, event
29 |
30 | @view_config(renderer='string')
31 | def theview(request):
32 | objectEventNotify(ObjectThrownEvent(Foo()))
33 | objectEventNotify(ObjectThrownEvent(None))
34 | objectEventNotify(ObjectEvent(Foo()))
35 | return 'OK'
36 |
37 | if __name__ == '__main__':
38 | from pyramid.config import Configurator
39 | from paste.httpserver import serve
40 | config = Configurator(autocommit=True)
41 | config.hook_zca()
42 | config.scan('__main__')
43 | serve(config.make_wsgi_app())
44 |
45 | The ``objectevent_listener`` listener defined above will only be called when
46 | the ``object`` of the ObjectThrownEvent is of class ``Foo``. We can tell
47 | that's the case because only the first call to objectEventNotify actually
48 | invokes the subscriber. The second and third calls to objectEventNotify do
49 | not call the subscriber. The second call doesn't invoke the subscriber
50 | because its object type is ``None`` (and not ``Foo``). The third call
51 | doesn't invoke the subscriber because its objectevent type is ObjectEvent
52 | (and not ``ObjectThrownEvent``). Clear as mud?
53 |
--------------------------------------------------------------------------------
/docs/misc/index.rst:
--------------------------------------------------------------------------------
1 | Miscellaneous
2 | %%%%%%%%%%%%%
3 |
4 | .. toctree::
5 | :maxdepth: 2
6 |
7 | interfaces
8 | events
9 | videos
10 |
--------------------------------------------------------------------------------
/docs/misc/interfaces.rst:
--------------------------------------------------------------------------------
1 | Interfaces
2 | ==========
3 |
4 | This chapter contains information about using ``zope.interface`` with
5 | Pyramid.
6 |
7 | Dynamically Compute the Interfaces Provided by an Object
8 | --------------------------------------------------------
9 |
10 | (Via Marius Gedminas)
11 |
12 | When persisting the interfaces that are provided by an object in a pickle or
13 | in ZODB is not reasonable for your application, you can use this trick to
14 | dynamically return the set of interfaces provided by an object based on other
15 | data in an instance of the object::
16 |
17 | from zope.interface.declarations import Provides
18 |
19 | from mypackage import interfaces
20 |
21 | class MyClass(object):
22 |
23 | color = None
24 |
25 | @property
26 | def __provides__(self):
27 | # black magic happens here: we claim to provide the right IFrob
28 | # subinterface depending on the value of the ``color`` attribute.
29 | iface = getattr(interfaces, 'I%sFrob' % self.color.title(),
30 | interfaces.IFrob))
31 | return Provides(self.__class__, iface)
32 |
33 | If you need the object to implement more than one interface, use
34 | ``Provides(self.__class__, iface1, iface2, ...)``.
35 |
--------------------------------------------------------------------------------
/docs/misc/videos.rst:
--------------------------------------------------------------------------------
1 | Pyramid Tutorial and Informational Videos
2 | -----------------------------------------
3 |
4 | * Six Feet Up's `Intro to Basic Pyramid
5 | `_.
6 |
7 | * Daniel Nouri's "Writing A Pyramid Application" (long, 3+ hours), from
8 | EuroPython 2012:
9 |
10 | - `Part 1 `_
11 |
12 | - `Part 2 `_
13 |
14 | See also the related `blog post `_.
15 |
16 | * Carlos de la Guardia's `Writing a Pyramid Application
17 | `_
18 | tutorial from PyCon 2012 (long, 3+ hours).
19 |
20 | * Dylan Jay's `Pyramid: Lighter, faster, better web apps
21 | `_ from PyCon AU 2011 (~37 mins).
22 |
23 | * Carlos de la Guardia's `Patterns for building large Pyramid applications
24 | `_ (~25 minutes).
25 |
26 | * Eric Bieschke's `Pyramid Turbo Start Tutorial
27 | `_ (very short, 2 mins, 2011).
28 |
29 | * Chris McDonough `presentation
30 | `_
31 | to Helsinki Python User's Group about Pyramid (2012), about 30 mins.
32 |
33 | * Chris McDonough at DjangoCon 2012, `About Django from the Pyramid Guy
34 | `_ (about 30 mins).
35 |
36 | * Chris McDonough and Mark Ramm: `FLOSS Weekly 151: The Pylons Project
37 | `_ (about 40 mins, 2010).
38 |
39 | * Kevin Gill's `What is Pyramid and where is it with respect to Django
40 | `_ (~43 mins) via Python Ireland May 2011.
41 |
42 | * Saiju M's `Create Pyramid Application With SQLAlchemy
43 | `_ (~ 17 mins).
44 |
45 | * George Dubus' `Pyramid advanced configuration tactics for nice apps and libs
46 | `_ from
47 | EuroPython 2013 (~34 mins).
48 |
49 | * Chris McDonough at PyCon 2013, `Pyramid Auth Is Hard, Let's Ride Bikes
50 | `_ (~30
51 | mins).
52 |
53 | * Dylan Jay's DjangoCon AU 2013 Keynote, `The myth of goldilocks and the three
54 | frameworks, Pyramid, Django, and Plone
55 | `_ (~45 mins).
56 |
57 | * Paul Everitt: `Python 3 Web Development with Pyramid and PyCharm
58 | `_
59 | (~1 hr).
60 |
--------------------------------------------------------------------------------
/docs/porting/index.rst:
--------------------------------------------------------------------------------
1 | .. _porting:
2 |
3 | Porting Applications to Pyramid
4 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5 |
6 | *Note:* Other articles about Pylons applications are in the
7 | :doc:`../pylons/index` section.
8 |
9 | .. toctree::
10 | :maxdepth: 2
11 |
12 | legacy
13 | wsgi
14 |
--------------------------------------------------------------------------------
/docs/porting/legacy.rst:
--------------------------------------------------------------------------------
1 | Porting a Legacy Pylons Application Piecemeal
2 | ---------------------------------------------
3 |
4 | You would like to move from Pylons 1.0 to Pyramid, but you're not going to be
5 | able manage a wholesale port any time soon. You're wondering if it would be
6 | practical to start using some parts of Pyramid within an existing Pylons
7 | project.
8 |
9 | One idea is to use a Pyramid "NotFound view" which delegates to the existing
10 | Pylons application, and port piecemeal::
11 |
12 | # ... obtain pylons WSGI application object ...
13 | from mypylonsproject import thepylonsapp
14 |
15 | class LegacyView(object):
16 | def __init__(self, app):
17 | self.app = app
18 | def __call__(self, request):
19 | return request.get_response(self.app)
20 |
21 | if __name__ == '__main__':
22 | legacy_view = LegacyView(thepylonsapp)
23 | config = Configurator()
24 | config.add_view(context='pyramid.exceptions.NotFound', view=legacy_view)
25 | # ... rest of config ...
26 |
27 | At that point, whenever Pyramid cannot service a request because the URL
28 | doesn't match anything, it will invoke the Pylons application as a fallback,
29 | which will return things normally. At that point you can start moving logic
30 | incrementally into Pyramid from the Pylons application until you've ported
31 | everything.
32 |
--------------------------------------------------------------------------------
/docs/porting/wsgi.rst:
--------------------------------------------------------------------------------
1 | Porting an Existing WSGI Application to Pyramid
2 | -----------------------------------------------
3 |
4 | Pyramid is cool, but already-working code is cooler. You may not have the
5 | time, money or energy to port an existing Pylons, Django, Zope, or other
6 | WSGI-based application to Pyramid wholesale. In such cases, it can be useful
7 | to *incrementally* port an existing application to Pyramid.
8 |
9 | The broad-brush way to do this is:
10 |
11 | - Set up an *exception view* that will be called whenever a NotFound
12 | exception is raised by Pyramid.
13 |
14 | - In this exception view, delegate to your already-written WSGI application.
15 |
16 | Here's an example::
17 |
18 | from pyramid.wsgi import wsgiapp2
19 | from pyramid.exceptions import NotFound
20 |
21 | if __name__ == '__main__':
22 | # during Pyramid configuration (usually in your Pyramid project's
23 | # __init__.py), get a hold of an instance of your existing WSGI
24 | # application.
25 | original_app = MyWSGIApplication()
26 |
27 | # using the pyramid.wsgi.wsgiapp2 wrapper function, wrap the
28 | # application into something that can be used as a Pyramid view.
29 | notfound_view = wsgiapp2(original_app)
30 |
31 | # in your configuration, use the wsgiapp2-wrapped application as
32 | # a NotFound exception view
33 | config = Configurator()
34 |
35 | # ... your other Pyramid configuration ...
36 | config.add_view(notfound_view, context=NotFound)
37 | # .. the remainder of your configuration ...
38 |
39 |
40 | When Pyramid cannot resolve a URL to a view, it will raise a NotFound
41 | exception. The ``add_view`` statement in the example above configures
42 | Pyramid to use your original WSGI application as the NotFound view. This
43 | means that whenever Pyramid cannot resolve a URL, your original application
44 | will be called.
45 |
46 | Incrementally, you can begin moving features from your existing WSGI
47 | application to Pyramid; if Pyramid can resolve a request to a view, the
48 | Pyramid "version" of the application logic will be used. If it cannot, the
49 | original WSGI application version of the logic will be used. Over time, you
50 | can move *all* of the logic into Pyramid without needing to do it all at
51 | once.
52 |
--------------------------------------------------------------------------------
/docs/pylons/code/alchemy_main.py:
--------------------------------------------------------------------------------
1 | from pyramid.config import Configurator
2 | from sqlalchemy import engine_from_config
3 |
4 | from .models import DBSession
5 |
6 | def main(global_config, **settings):
7 | """ This function returns a Pyramid WSGI application.
8 | """
9 | engine = engine_from_config(settings, 'sqlalchemy.')
10 | DBSession.configure(bind=engine)
11 | config = Configurator(settings=settings)
12 | config.add_static_view('static', 'static', cache_max_age=3600)
13 | config.add_route('home', '/')
14 | config.scan()
15 | return config.make_wsgi_app()
16 |
17 |
--------------------------------------------------------------------------------
/docs/pylons/code/model_development.ini:
--------------------------------------------------------------------------------
1 | # development.ini
2 | [app:main]
3 |
4 | # Pyramid only
5 | pyramid.includes =
6 | pyramid_tm
7 |
8 | # Pyramid and Pylons
9 | sqlalchemy.url = sqlite:///%(here)s/PyramidApp.db
10 |
11 |
12 | [logger_sqlalchemy]
13 |
14 | # Pyramid and Pylons
15 | level = INFO
16 | handlers =
17 | qualname = sqlalchemy.engine
18 | # "level = INFO" logs SQL queries.
19 | # "level = DEBUG" logs SQL queries and results.
20 | # "level = WARN" logs neither. (Recommended for production systems.)
21 |
--------------------------------------------------------------------------------
/docs/pylons/code/models.py:
--------------------------------------------------------------------------------
1 | # pyramidapp/__init__.py
2 | from sqlalchemy import engine_from_config
3 | from .models import DBSession
4 |
5 | def main(global_config, **settings):
6 | engine = engine_from_config(settings, 'sqlalchemy.')
7 | DBSession.configure(bind=engine)
8 | ...
9 |
10 |
11 | # pyramidapp/models.py
12 | from sqlalchemy import Column, Integer, Text
13 | from sqlalchemy.ext.declarative import declarative_base
14 | from sqlalchemy.orm import scoped_session, sessionmaker
15 | from zope.sqlalchemy import ZopeTransactionExtension
16 |
17 | DBSession = scoped_session(sessionmaker(extension=ZopeTransactionExtension()))
18 | Base = declarative_base()
19 |
20 | class MyModel(Base):
21 | __tablename__ = 'models'
22 | id = Column(Integer, primary_key=True)
23 | name = Column(Text, unique=True)
24 | value = Column(Integer)
25 |
26 | def __init__(self, name, value):
27 | self.name = name
28 | self.value = value
29 |
30 |
--------------------------------------------------------------------------------
/docs/pylons/code/pyramid_handlers.py:
--------------------------------------------------------------------------------
1 | # In the top-level __init__.py
2 | from .handlers import Hello
3 | def main(global_config, **settings):
4 | ...
5 | config.include("pyramid_handlers")
6 | config.add_handler("hello", "/hello/{action}", handler=Hello)
7 |
8 | # In zzz/handlers.py
9 | from pyramid_handlers import action
10 | class Hello(object):
11 | __autoexpose__ = None
12 |
13 | def __init__(self, request):
14 | self.request = request
15 |
16 | @action
17 | def index(self):
18 | return Response('Hello world!')
19 |
20 | @action(renderer="mytemplate.mak")
21 | def bye(self):
22 | return {}
23 |
--------------------------------------------------------------------------------
/docs/pylons/code/starter_main.py:
--------------------------------------------------------------------------------
1 | from pyramid.config import Configurator
2 |
3 | def main(global_config, **settings):
4 | """ This function returns a Pyramid WSGI application.
5 | """
6 | config = Configurator(settings=settings)
7 | config.add_static_view('static', 'static', cache_max_age=3600)
8 | config.add_route('home', '/')
9 | config.scan()
10 | return config.make_wsgi_app()
11 |
--------------------------------------------------------------------------------
/docs/pylons/deployment.rst:
--------------------------------------------------------------------------------
1 | Deployment
2 | ++++++++++
3 |
4 | Deployment is the same for Pyramid as for Pylons. Specify the desired WSGI
5 | server in the "[server:main]" and run "pserve" with it. The default server in
6 | Pyramid is Waitress, compared to PasteHTTPServer in Pylons.
7 |
8 | Waitress' advantage is that it runs on Python 3. Its disadvantage is that it
9 | doesn't seek and destroy stuck threads like PasteHTTPServer does. If you're
10 | like me, that's enough reason not to use Waitress in production. You can switch
11 | to PasteHTTPServer or CherryPy server if you wish, or use a method like
12 | mod_wsgi that doesn't require a Python HTTP server.
13 |
--------------------------------------------------------------------------------
/docs/pylons/index.rst:
--------------------------------------------------------------------------------
1 | Pyramid for Pylons Users
2 | ++++++++++++++++++++++++
3 |
4 | :Updated: 2012-06-12
5 | :Versions: Pyramid 1.3
6 | :Author: Mike Orr
7 | :Contributors:
8 |
9 | This guide discusses how Pyramid 1.3 differs from Pylons 1, and a few ways to
10 | make it more like Pylons. The guide may also be helpful to readers coming from
11 | Django or another Rails-like framework. The author has been a Pylons developer
12 | since 2007. The examples are based on Pyramid's default SQLAlchemy application
13 | and on the Akhet_ demo.
14 |
15 | If you haven't used Pyramid yet you can read this guide to get an overview of
16 | the differences and the Pyramid API. However, to actually start using Pyramid
17 | you'll want to read at least the first five chapters of the `Pyramid
18 | manual`_ (through `Creating a Pyramid Project`_) and go through the Tutorials_.
19 | Then you can come back to this guide to start designing your application, and
20 | skim through the rest of the manual to see which sections cover which topics.
21 |
22 | .. toctree::
23 | :maxdepth: 1
24 |
25 | intro
26 | launch
27 | ini_file
28 | main
29 | models
30 | views
31 | examples
32 | request
33 | templates
34 | exceptions
35 | static
36 | sessions
37 | deployment
38 | auth
39 | other
40 | migrate
41 |
42 |
43 | .. include:: ../links.rst
44 |
--------------------------------------------------------------------------------
/docs/pylons/launch.rst:
--------------------------------------------------------------------------------
1 | Launching the Application
2 | +++++++++++++++++++++++++
3 |
4 | Pyramid and Pylons start up identically because they both use PasteDeploy and
5 | its INI-format configuration file. This is true even though Pyramid 1.3
6 | replaced "paster serve" with its own "pserve" command. Both "pserve" and
7 | "paster serve" do the following:
8 |
9 | 1. Read the INI file.
10 | 2. Instantiate an application based on the "[app:main]" section.
11 | 3. Instantiate a server based on the "[server:main]" section.
12 | 4. Configure Python logging based on the logging sections.
13 | 5. Call the server with the application.
14 |
15 | Steps 1-3 and 5 are essentially wrappers around PasteDeploy. Only step 2 is
16 | really "using Pyramid", because only the application depends on other parts of
17 | Pyramid. The rest of the routine is copied directly from "paster serve" and
18 | does not depend on other parts of Pyramid.
19 |
20 | The way the launcher instantiates an application is often misunderstood so
21 | let's stop for a moment and detail it. Here's part of the app section in the
22 | Akhet Demo:
23 |
24 | .. code-block:: ini
25 |
26 | [app:main]
27 | use = egg:akhet_demo#main
28 | pyramid.reload_templates = true
29 | pyramid.debug_authorization = false
30 |
31 | The "use=" line indirectly names a Python callable to load. "egg:" says to look up a
32 | Python object by entry point. (Entry points are a feature provided by
33 | Setuptools, which is why Pyramid/Pylons require it or Distribute to be
34 | installed.) "akhet_demo" is the name of the Python
35 | distribution to look in (the Pyramid application), and "main" is the entry
36 | point. The launcher calls
37 | ``pkg_resources.require("akhet_demo#main")`` in Setuptools, and Setuptools
38 | returns the Python object. Entry points are defined in the distribution's
39 | setup.py, and the installer writes them to an entry points file. Here's the
40 | *akhet_demo.egg-info/entry_points.txt* file:
41 |
42 | .. code-block:: ini
43 |
44 | [paste.app_factory]
45 | main = akhet_demo:main
46 |
47 | "paste.app_factory" is the entry point group, a name publicized in the
48 | PasteDeploy docs for all applications that want to be compatible with it.
49 | "main" (on the left side of the equal sign) is the entry point.
50 | "akhet_demo:main" says to import the ``akhet_demo`` package and load a "main"
51 | attribute. This is our ``main()`` function defined in
52 | *akhet_demo/\_\_init\_\_.py*. The other options in the "[app:main]" section
53 | become keyword arguments to this callable. These options are called "settings"
54 | in Pyramid and "config variables" in Pylons. (The options in the "[DEFAULT]"
55 | section are also passed as default values.) Both frameworks provide a way to
56 | access these variables in application code. In Pyramid they're in the
57 | ``request.registry.settings`` dict. In Pylons they're in the ``pylons.config``
58 | magic global.
59 |
60 | The launcher loads the server in the same way, using the "[server:main]"
61 | section.
62 |
63 | *More details:* The heavy lifting is done by ``loadapp()`` and ``loadserver()``
64 | in ``paste.deploy.loadwsgi``. Loadwsgi is obtuse and undocumented, but
65 | ``pyramid.paster`` has some convenience functions that either call or mimic some of
66 | its routines.
67 |
68 | Alternative launchers such as mod_wsgi read only the "[app:main]" section and
69 | ignore the server section, but they're still using PasteDeploy or the
70 | equivalent. It's also possible to instantiate the application manually without an
71 | INI file or PasteDeploy, as we'll see in the chapter called "The Main Function".
72 |
73 | Now that we know more about how the launcher loads the application, let's look
74 | closer at a Pyramid application itself.
75 |
--------------------------------------------------------------------------------
/docs/pylons/migrate.rst:
--------------------------------------------------------------------------------
1 | Migrating an Existing Pylons Application
2 | ++++++++++++++++++++++++++++++++++++++++
3 |
4 | There are two general ways to port a Pylons application to Pyramid. One is to
5 | start from scratch, expressing the application's behavior in Pyramid. Many
6 | aspects such as the models, templates, and static files can be used unchanged
7 | or mostly unchanged. Other aspects like such as the controllers and globals
8 | will have to be rewritten. The route map can be ported to the new syntax, or
9 | you can take the opportunity to restructure your routes.
10 |
11 | The other way is to port one URL at a time, and let Pyramid serve the ported
12 | URLs and Pylons serve the unported URLs. There are several ways to do this:
13 |
14 | * Run both the Pyramid and Python applications in Apache, and use mod_rewrite
15 | to send different URLs to different applications.
16 | * Set up ``paste.cascade`` in the INI file, so that it will first try one
17 | application and then the other if the URL returns "Not Found". (This is how
18 | Pylons serves static files.)
19 | * Wrap the Pylons application in a Pyramid view. See pyramid.wsgiapp.wsgiapp2_.
20 |
21 | Also see the :ref:`porting` section in the Cookbook.
22 |
23 | *Caution:* running a Pyramid and a Pylons application simultaneously may bring up
24 | some tricky issues such as coordiating database connections, sessions, data
25 | files, etc. These are beyond the scope of this Guide.
26 |
27 | You'll also have to choose whether to write the Pyramid application in Python 2
28 | or 3. Pyramid 1.3 runs on Python 3, along with Mako and SQLAlchemy, and the
29 | Waitress and CherryPy HTTP servers (but not PasteHTTPServer). But not all
30 | optional libraries have been ported yet, and your application may depend on
31 | libraries which haven't been.
32 |
33 |
34 | .. include:: ../links.rst
35 |
36 |
37 | .. _pyramid.wsgiapp.wsgiapp2: https://docs.pylonsproject.org/projects/pyramid/en/latest/api/wsgi.html#pyramid.wsgi.wsgiapp2
38 |
--------------------------------------------------------------------------------
/docs/pylons/sessions.rst:
--------------------------------------------------------------------------------
1 | Sessions
2 | ++++++++
3 |
4 | Pyramid uses Beaker sessions just like Pylons, but they're not enabled by
5 | default. To use them you'll have to add the "pyramid_beaker" package as a
6 | dependency, and put the following line in your ``main()`` function::
7 |
8 | config.include("pyramid_beaker")
9 |
10 | (To add a dependency, put it in the ``requires`` list in setup.py, and
11 | reinstall the application.)
12 |
13 | The default configuration is in-memory sessions and (I think) no caching. You
14 | can customize this by putting configuration settings in your INI file or in the
15 | ``settings`` dict at the beginning of the ``main()`` function (before the
16 | Configurator is instantiated). The Akhet Demo configures Beaker with the
17 | following settings, borrowed from the Pylons configuration:
18 |
19 | .. code-block:: ini
20 |
21 | # Beaker cache
22 | cache.regions = default_term, second, short_term, long_term
23 | cache.type = memory
24 | cache.second.expire = 1
25 | cache.short_term.expire = 60
26 | cache.default_term.expire = 300
27 | cache.long_term.expire = 3600
28 |
29 | # Beaker sessions
30 | #session.type = file
31 | #session.data_dir = %(here)s/data/sessions/data
32 | #session.lock_dir = %(here)s/data/sessions/lock
33 | session.type = memory
34 | session.key = akhet_demo
35 | session.secret = 0cb243f53ad865a0f70099c0414ffe9cfcfe03ac
36 |
37 | To use file-based sessions like in Pylons, uncomment the first three session
38 | settings and comment out the "session.type = memory" line.
39 |
40 | You should set the "session.secret=" setting to a random string. It's used to
41 | digitally sign the session cookie to prevent session hijacking.
42 |
43 | Beaker has several persistence backends available, including memory, files,
44 | SQLAlchemy, memcached, and cookies (which stores each session variable in a
45 | client-side cookie, and has size limitationss). The most popular
46 | deployment backend nowadays is memcached, which can act as a shared storage
47 | between several processes and servers, thus providing the speed of memory with
48 | the ability to scale to a multi-server cluster. Pylons defaults to disk-based
49 | sessions.
50 |
51 | Beaker plugs into Pyramid's built-in session interface, which is accessed via
52 | ``request.session``. Use it like a dict. Unlike raw Beaker sessions, you don't
53 | have to call ``session.save()`` every time you change something, but you should
54 | call ``session.changed()`` if you've modified a *mutable* item in the session;
55 | e.g., ``session["mylist"].append(1)``.
56 |
57 | The Pyramid session interface also has some extra features. It can store a set
58 | of "flash messages" to display on the next page view, which is useful when you
59 | want to push a success/failure message and redirect, and the message will be
60 | displayed on the target page. It's based on ``webhelpers.flash``, which is
61 | incompatible with Pyramid because it depends on Pylons' magic globals. There
62 | are also methods to set a secure form token, which prevent form submissions
63 | that didn't come from a form requested earlier in the session (and thus may be
64 | a cross-site forgery attack). (Note: flash messages are not related to the Adobe
65 | Flash movie player.)
66 |
67 | See the :ref:`sessions_chapter` chapter in the Pyramid manual for the API of
68 | all these features and other features. The Beaker_ manual will help you
69 | configure a backend. The Akhet_ Demo is an example of using Pyramid with
70 | Beaker, and has flash messages.
71 |
72 | *Note:* I sometimes get an exception in the debug toolbar when sessions are
73 | enabled. They may be a code discrepency between the distributions. If this
74 | happens to you, you can disable the toolbar until the problem is fixed.
75 |
76 |
77 | .. include:: ../links.rst
78 |
--------------------------------------------------------------------------------
/docs/routing/index.rst:
--------------------------------------------------------------------------------
1 | Routing: Traversal and URL Dispatch
2 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 |
4 | .. toctree::
5 | :maxdepth: 2
6 |
7 | combining
8 | traversal_in_views
9 | traversal_sqlalchemy
10 |
11 | For more information on URL dispatch, see the `URL Dispatch
12 | `_
13 | section of the Pyramid documentation.
14 |
15 | For more information traversal, see the following sections of the Pyramid
16 | documentation:
17 |
18 | - `Hello Traversal `_
19 | - `Much Ado about Traversal `_
20 | - `Traversal `_
21 | - `Hybrid Dispatching `_
22 | - `Virtual Hosting `_
23 |
--------------------------------------------------------------------------------
/docs/routing/traversal_in_views.rst:
--------------------------------------------------------------------------------
1 | .. _traversal_in_views:
2 |
3 | Using Traversal in Pyramid Views
4 | ================================
5 |
6 | A trivial example of how to use :term:`traversal` in your view code.
7 |
8 | You may remember that a Pyramid :term:`view` is called with a
9 | :term:`context` argument.
10 |
11 | .. code-block:: python
12 |
13 | def my_view(context, request):
14 | return render_view_to_response(context, request)
15 |
16 |
17 | When using traversal, ``context`` will be the :term:`resource` object
18 | that was found by traversal. Configuring which resources a view
19 | responds to can be done easily via either the ``@view.config``
20 | decorator.
21 |
22 | .. code-block:: python
23 |
24 | from models import MyResource
25 |
26 | @view_config(context=MyResource)
27 | def my_view(context, request):
28 | return render_view_to_response(context, request)
29 |
30 | or via ``config.add_view``::
31 |
32 | from models import MyResource
33 | config = Configurator()
34 | config.add_view('myapp.views.my_view', context=MyResource)
35 |
36 | Either way, any request that triggers traversal and traverses to a
37 | ``MyResource`` instance will result in calling this view with that
38 | instance as the ``context`` argument.
39 |
40 | Optional: Using Interfaces
41 | --------------------------
42 |
43 | If your resource classes implement :term:`interfaces `,
44 | you can configure your views by interface. This is one way to decouple
45 | view code from a specific resource implementation.
46 |
47 | .. code-block:: python
48 |
49 | # models.py
50 | from zope.interface import implements
51 | from zope.interface import Interface
52 |
53 | class IMyResource(Interface):
54 | pass
55 |
56 | class MyResource(object):
57 | implements(IMyResource)
58 |
59 | # views.py
60 | from models import IMyResource
61 |
62 | @view_config(context=IMyResource)
63 | def my_view(context, request):
64 | return render_view_to_response(context, request)
65 |
66 |
67 | See Also
68 | --------
69 |
70 | - :ref:`much_ado_about_traversal_chapter`
71 |
72 | - :ref:`comparing_traversal_and_dispatch`
73 |
74 | - The "Virginia" sample application: https://github.com/Pylons/virginia/blob/master/virginia/views.py
75 |
76 | - ZODB and Traversal in Pyramid tutorial: https://docs.pylonsproject.org/projects/pyramid/en/latest/tutorials/wiki/index.html#bfg-wiki-tutorial
77 |
78 | - Resources which implement interfaces: https://docs.pylonsproject.org/projects/pyramid/en/latest/narr/resources.html#resources-which-implement-interfaces
79 |
--------------------------------------------------------------------------------
/docs/sample_applications/index.rst:
--------------------------------------------------------------------------------
1 | Sample Pyramid Applications
2 | %%%%%%%%%%%%%%%%%%%%%%%%%%%
3 |
4 | This section is a collection of sample Pyramid applications.
5 |
6 | If you know of other applications, please submit an issue or pull request via
7 | the `Pyramid Community Cookbook repo on GitHub
8 | `_ to add it to this list.
9 |
10 |
11 | .. toctree::
12 | :maxdepth: 2
13 |
14 | single_file_tasks
15 |
--------------------------------------------------------------------------------
/docs/sample_applications/single_file_tasks.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pylons/pyramid_cookbook/35bbfad6637ea85adbf0e18d168b8ecc3d01707d/docs/sample_applications/single_file_tasks.png
--------------------------------------------------------------------------------
/docs/sample_applications/single_file_tasks_src/.gitignore:
--------------------------------------------------------------------------------
1 | .installed.cfg
2 | bin/
3 | bootstrap.py
4 | eggs
5 | parts/
6 | tasks.db
7 | var/
8 | *.pyc
9 | *.swp
10 |
--------------------------------------------------------------------------------
/docs/sample_applications/single_file_tasks_src/Makefile:
--------------------------------------------------------------------------------
1 | SHELL = /bin/bash
2 | WGET = wget
3 |
4 | PYTHON_VERSION := $(shell python -V 2>&1)
5 | BOOTSTRAP_PY_URL = http://svn.zope.org/*checkout*/zc.buildout/branches/2/bootstrap/bootstrap.py
6 |
7 | run: bin/python
8 | bin/python tasks.py
9 |
10 | bin/python: bin/buildout buildout.cfg
11 | if [[ "$(PYTHON_VERSION)" == Python\ 3* ]]; then echo "*** Python 3 ***"; bin/buildout -c buildout-py3.cfg; else echo "*** Python 2 ***"; bin/buildout; fi
12 |
13 | run-buildout: bin/buildout buildout.cfg
14 | bin/buildout
15 |
16 | bin/buildout: bootstrap.py
17 | python bootstrap.py
18 |
19 | bootstrap.py:
20 | $(WGET) -O bootstrap.py $(BOOTSTRAP_PY_URL)
21 |
22 | clean:
23 | $(RM) -r bin bootstrap.py develop-eggs eggs parts tasks.db var .installed.cfg
24 |
--------------------------------------------------------------------------------
/docs/sample_applications/single_file_tasks_src/buildout.cfg:
--------------------------------------------------------------------------------
1 | [buildout]
2 | parts =
3 | python
4 |
5 | [python]
6 | recipe = zc.recipe.egg
7 | eggs =
8 | pyramid
9 | interpreter = python
10 |
--------------------------------------------------------------------------------
/docs/sample_applications/single_file_tasks_src/schema.sql:
--------------------------------------------------------------------------------
1 | create table if not exists tasks (
2 | id integer primary key autoincrement,
3 | name char(100) not null,
4 | closed bool not null
5 | );
6 |
7 | insert or ignore into tasks (id, name, closed) values (0, 'Start learning Pyramid', 0);
8 | insert or ignore into tasks (id, name, closed) values (1, 'Do quick tutorial', 0);
9 | insert or ignore into tasks (id, name, closed) values (2, 'Have some beer!', 0);
10 |
11 |
--------------------------------------------------------------------------------
/docs/sample_applications/single_file_tasks_src/static/style.css:
--------------------------------------------------------------------------------
1 | body {
2 | font-family: sans-serif;
3 | font-size: 14px;
4 | color: #3e4349;
5 | }
6 |
7 | h1, h2, h3, h4, h5, h6 {
8 | font-family: Georgia;
9 | color: #373839;
10 | }
11 |
12 | a {
13 | color: #1b61d6;
14 | text-decoration: none;
15 | }
16 |
17 | input {
18 | font-size: 14px;
19 | width: 400px;
20 | border: 1px solid #bbbbbb;
21 | padding: 5px;
22 | }
23 |
24 | .button {
25 | font-size: 14px;
26 | font-weight: bold;
27 | width: auto;
28 | background: #eeeeee;
29 | padding: 5px 20px 5px 20px;
30 | border: 1px solid #bbbbbb;
31 | border-left: none;
32 | border-right: none;
33 | }
34 |
35 | #flash, #notfound {
36 | font-size: 16px;
37 | width: 500px;
38 | text-align: center;
39 | background-color: #e1ecfe;
40 | border-top: 2px solid #7a9eec;
41 | border-bottom: 2px solid #7a9eec;
42 | padding: 10px 20px 10px 20px;
43 | }
44 |
45 | #notfound {
46 | background-color: #fbe3e4;
47 | border-top: 2px solid #fbc2c4;
48 | border-bottom: 2px solid #fbc2c4;
49 | padding: 0 20px 30px 20px;
50 | }
51 |
52 | #tasks {
53 | width: 500px;
54 | }
55 |
56 | #tasks li {
57 | padding: 5px 0 5px 0;
58 | border-bottom: 1px solid #bbbbbb;
59 | }
60 |
61 | #tasks li.last {
62 | border-bottom: none;
63 | }
64 |
65 | #tasks .name {
66 | width: 400px;
67 | text-align: left;
68 | display: inline-block;
69 | }
70 |
71 | #tasks .actions {
72 | width: 80px;
73 | text-align: right;
74 | display: inline-block;
75 | }
--------------------------------------------------------------------------------
/docs/sample_applications/single_file_tasks_src/templates/layout.mako:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 |
4 |
5 |
6 |
7 | Pyramid Task's List Tutorial
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | % if request.session.peek_flash():
17 |