Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -26,7 +26,16 @@ By default, this module contains a special method, ``init_model``::
|
||||
from pecan import conf
|
||||
|
||||
def init_model():
|
||||
# Read and parse database bindings from pecan.conf
|
||||
"""
|
||||
This is a stub method which is called at application startup time.
|
||||
|
||||
If you need to bind to a parse database configuration, set up tables or
|
||||
ORM classes, or perform any database initialization, this is the
|
||||
recommended place to do it.
|
||||
|
||||
For more information working with databases, and some common recipes,
|
||||
see http://pecan.readthedocs.org/en/latest/databases.html
|
||||
"""
|
||||
pass
|
||||
|
||||
The purpose of this method is to determine bindings from your configuration file and create
|
||||
@@ -91,7 +100,7 @@ Binding Within the Application
|
||||
There are several approaches that can be taken to wrap your application's requests with calls
|
||||
to appropriate model function calls. One approach is WSGI middleware. We also recommend
|
||||
Pecan :ref:`hooks`. Pecan comes with ``TransactionHook``, a hook which can
|
||||
be used to wrap requests in transactions for you. To use it, simply include it in your
|
||||
be used to wrap requests in database transactions for you. To use it, simply include it in your
|
||||
project's ``app.py`` file and pass it a set of functions related to database binding::
|
||||
|
||||
from pecan import conf, make_app
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
.. _deployment:
|
||||
|
||||
Deployment Recipes
|
||||
=============
|
||||
|
||||
@@ -63,10 +63,8 @@ tutorial on App Engine.
|
||||
|
||||
app_engine.rst
|
||||
sessions.rst
|
||||
celery.rst
|
||||
databases.rst
|
||||
deployment.rst
|
||||
reporting.rst
|
||||
|
||||
|
||||
API Documentation
|
||||
|
||||
@@ -3,40 +3,40 @@
|
||||
Installation
|
||||
============
|
||||
|
||||
.. warning::
|
||||
This section is out of date. Please do not refer to it directly.
|
||||
Stable Version
|
||||
------------------------------
|
||||
|
||||
We recommend installing Pecan with ``pip`` but you can also try with
|
||||
``easy_install`` and ``virtualenv``. Creating a spot in your environment where
|
||||
Pecan can be isolated from other packages is best practice.
|
||||
|
||||
To get started with an environment for Pecan, create a virtual environment for
|
||||
it without any site-packages that might pollute::
|
||||
To get started with an environment for Pecan, create a new
|
||||
`virtual environment <http://www.virtualenv.org>`_::
|
||||
|
||||
virtualenv --no-site-packages pecan-env
|
||||
cd pecan-env
|
||||
source bin/activate
|
||||
|
||||
The above commands created a virtual environment and *activated* it. Those
|
||||
actions will encapsulate anything that we do with the framework, making it
|
||||
easier to debug problems if needed.
|
||||
The above commands create a virtual environment and *activate* it. Those
|
||||
actions will encapsulate any dependency installations for the framework,
|
||||
making it easier to debug problems if needed.
|
||||
|
||||
But we do not have Pecan yet, so let's grab it from PYPI::
|
||||
Next, let's install Pecan::
|
||||
|
||||
pip install pecan
|
||||
|
||||
After a lot of output, you should have Pecan successfully installed and ready
|
||||
to use.
|
||||
After a lot of output, you should have Pecan successfully installed.
|
||||
|
||||
|
||||
Development (Unstable) Version
|
||||
------------------------------
|
||||
If you want to run the development version of Pecan you will
|
||||
need GIT installed and clone the repo from github::
|
||||
need to install git and clone the repo from github::
|
||||
|
||||
git clone https://github.com/pecan/pecan.git
|
||||
|
||||
If you are still in the *pecan-dev* virtual environment that we created before,
|
||||
you should call ``setup.py`` to install::
|
||||
If your virtual environment is still activated, call ``setup.py`` to install
|
||||
the development version::
|
||||
|
||||
cd pecan
|
||||
python setup.py develop
|
||||
|
||||
@@ -3,69 +3,33 @@
|
||||
Quick Start
|
||||
===========
|
||||
|
||||
Here we will cover the basics for a small project in Pecan. More advanced
|
||||
examples and methods are not covered here.
|
||||
Let's create a small sample project with Pecan.
|
||||
|
||||
.. note::
|
||||
We will not cover how to get Pecan installed here. If you need installation
|
||||
details please go to :ref:`installation` which includes the recommended way
|
||||
of setting up a proper development environment.
|
||||
This guide does not cover the installation of Pecan. If you need
|
||||
instructions for installing Pecan, go to :ref:`installation`.
|
||||
|
||||
|
||||
Base Application Template
|
||||
-------------------------
|
||||
|
||||
We include a basic template to have a good layout for a Pecan project. This is
|
||||
accomplished by the ``pecan`` command line script bundled with the framework.
|
||||
Invoking the command to create a project is trivial::
|
||||
A basic template for getting started is included with Pecan. From
|
||||
your shell, type::
|
||||
|
||||
$ pecan create -t base
|
||||
$ pecan create
|
||||
|
||||
The above command will prompt you for a project name. I chose *test_project*,
|
||||
but you can also provided as an argument at the end of the example command
|
||||
above, like::
|
||||
|
||||
$ pecan create -t base test_project
|
||||
$ pecan create test_project
|
||||
|
||||
This is how it looks like when we run the whole command::
|
||||
Go ahead and change into your newly created project directory::
|
||||
|
||||
$ pecan create -t base
|
||||
Selected and implied templates:
|
||||
pecan#pecan-base Template for creating a basic Framework package
|
||||
$ cd test_project
|
||||
$ ls
|
||||
|
||||
Enter project name: test_project
|
||||
Variables:
|
||||
egg: test_project
|
||||
package: test_project
|
||||
project: test_project
|
||||
Creating template pecan-base
|
||||
Creating directory ./test_project
|
||||
Recursing into +egg+
|
||||
Creating ./test_project/test_project/
|
||||
Copying __init__.py to ./test_project/test_project/__init__.py
|
||||
Recursing into controllers
|
||||
Creating ./test_project/test_project/controllers/
|
||||
Copying __init__.py to ./test_project/test_project/controllers/__init__.py
|
||||
Copying root.py to ./test_project/test_project/controllers/root.py
|
||||
Recursing into model
|
||||
Creating ./test_project/test_project/model/
|
||||
Copying __init__.py to ./test_project/test_project/model/__init__.py
|
||||
Recursing into templates
|
||||
Creating ./test_project/test_project/templates/
|
||||
Copying index.html to ./test_project/test_project/templates/index.html
|
||||
Copying layout.html to ./test_project/test_project/templates/layout.html
|
||||
Copying success.html to ./test_project/test_project/templates/success.html
|
||||
Recursing into public
|
||||
Creating ./test_project/public/
|
||||
Recursing into css
|
||||
Creating ./test_project/public/css/
|
||||
Copying style.css to ./test_project/public/css/style.css
|
||||
Recursing into javascript
|
||||
Creating ./test_project/public/javascript/
|
||||
Copying shared.js to ./test_project/public/javascript/shared.js
|
||||
|
||||
|
||||
This is how the structure of your new project should look like::
|
||||
This is how the layout of your new project should look::
|
||||
|
||||
├── MANIFEST.in
|
||||
├── config.py
|
||||
@@ -74,77 +38,67 @@ This is how the structure of your new project should look like::
|
||||
│ │ └── style.css
|
||||
│ └── javascript
|
||||
│ └── shared.js
|
||||
├── setup.cfg
|
||||
├── setup.py
|
||||
├── test_project
|
||||
│ ├── __init__.py
|
||||
│ ├── app.py
|
||||
│ ├── controllers
|
||||
│ │ ├── __init__.py
|
||||
│ │ └── root.py
|
||||
│ ├── model
|
||||
│ │ └── __init__.py
|
||||
│ ├── templates
|
||||
│ │ ├── error.html
|
||||
│ │ ├── index.html
|
||||
│ │ ├── layout.html
|
||||
│ │ └── success.html
|
||||
│ └── tests
|
||||
│ ├── __init__.py
|
||||
│ ├── test_config.py
|
||||
│ └── test_root.py
|
||||
└── test_project.egg-info
|
||||
├── PKG-INFO
|
||||
├── SOURCES.txt
|
||||
├── dependency_links.txt
|
||||
├── not-zip-safe
|
||||
├── paster_plugins.txt
|
||||
├── requires.txt
|
||||
└── top_level.txt
|
||||
└── test_project
|
||||
├── __init__.py
|
||||
├── app.py
|
||||
├── controllers
|
||||
│ ├── __init__.py
|
||||
│ └── root.py
|
||||
├── model
|
||||
│ └── __init__.py
|
||||
├── templates
|
||||
│ ├── error.html
|
||||
│ ├── index.html
|
||||
│ ├── layout.html
|
||||
│ └── success.html
|
||||
└── tests
|
||||
├── __init__.py
|
||||
├── test_config.py
|
||||
└── test_root.py
|
||||
|
||||
9 directories, 25 files
|
||||
The amount of files and directories may vary, but the above structure should
|
||||
give you an idea of what you should expect.
|
||||
|
||||
The amount of files and directories may vary from time to time, but the above
|
||||
structure should give you an idea of what you should expect.
|
||||
A few things have been created for you, so let's review them one by one:
|
||||
|
||||
A few things have been set for you, let's review them one by one:
|
||||
|
||||
* **public**: All your public static files like CSS and Javascript are placed
|
||||
here. If you have some images (this example app doesn't) it would make sense
|
||||
to get them here as well.
|
||||
* **public**: All your static files (like CSS and Javascript) live here. If you
|
||||
have any images (this example app doesn't) they would live here too.
|
||||
|
||||
|
||||
Inside the project name you chose you have a few directories, and for the
|
||||
most part, it will contain your models, controllers and templates:
|
||||
The remaining directories encompass your models, controllers and templates, and
|
||||
tests:
|
||||
|
||||
* **controllers**: The container directory for your controller files.
|
||||
* **templates**: All your templates would go in here.
|
||||
* **model**: Container for your model files.
|
||||
* **tests**: All your application test files.
|
||||
* **test_project/controllers**: The container directory for your controller files.
|
||||
* **test_project/templates**: All your templates go in here.
|
||||
* **test_project/model**: Container for your model files.
|
||||
* **test_project/tests**: All of the tests for your application.
|
||||
|
||||
To avoid unneeded dependencies and to remain as flexible as possible, Pecan doesn't impose any database or
|
||||
ORM (Object Relational Mapper) out of the box. You may notice that **model/__init__.py** is mostly empty.
|
||||
Its contents generally contain any code necessary to define tables, ORM definitions, and parse bindings from
|
||||
your configuration file.
|
||||
To avoid unneeded dependencies and to remain as flexible as possible, Pecan
|
||||
doesn't impose any database or ORM (Object Relational Mapper) out of the box.
|
||||
You may notice that **model/__init__.py** is mostly empty. You may wish to add
|
||||
code here to define tables, ORM definitions, and parse bindings from your
|
||||
configuration file.
|
||||
|
||||
|
||||
.. note::
|
||||
With your base project you also got some ready-to-run tests. Try running
|
||||
``py.test`` (the recommended test runner for Pecan) and see them passing!
|
||||
The base project contains some ready-to-run tests. Try running
|
||||
``py.test`` (the recommended test runner for Pecan) and watch them pass!
|
||||
|
||||
|
||||
.. _running_application:
|
||||
|
||||
Running the application
|
||||
-----------------------
|
||||
The most important file to run your application is your configuration file, the
|
||||
base project template should have created one for you already and it should be
|
||||
named ``config.py``.
|
||||
Before starting up your Pecan app, you'll need a configuration file. The
|
||||
base project template should have created one for you already, ``config.py``.
|
||||
|
||||
This file already contains the necessary information to run a Pecan app, like
|
||||
ports, static paths and so forth.
|
||||
|
||||
If you just run ``pecan serve`` passing ``config.py`` as an argument for
|
||||
configuration it will bring up the development server and serve the app::
|
||||
If you just run ``pecan serve``, passing ``config.py`` as an argument for
|
||||
configuration, it will bring up the development server and serve the app::
|
||||
|
||||
$ pecan serve config.py
|
||||
Starting subprocess with file monitor
|
||||
@@ -152,27 +106,15 @@ configuration it will bring up the development server and serve the app::
|
||||
serving on 0.0.0.0:8080 view at http://127.0.0.1:8080
|
||||
|
||||
|
||||
To get up and running in no time the template helps a lot!
|
||||
|
||||
.. note::
|
||||
If you fail to pass an argument you will get a small error message asking
|
||||
for a configuration file.
|
||||
|
||||
The location for the config file and the argument itself are very flexible. You
|
||||
can pass an absolute path or just the name of the file without an extension,
|
||||
like::
|
||||
|
||||
$ pecan serve config
|
||||
The location for the config file and the argument itself are very flexible -
|
||||
you can pass an absolute or relative path to the file.
|
||||
|
||||
|
||||
Simple Configuration
|
||||
--------------------
|
||||
We mentioned that you get a Python file with some configurations. The only
|
||||
Python syntax that you will see is the first line that imports the
|
||||
RootController that is in turn placed as the application root. Everything else,
|
||||
including possible custom configurations are set as Python dictionaries.
|
||||
For ease of use, Pecan configuration files are pure Python.
|
||||
|
||||
This is how your default configuration file should look like::
|
||||
This is how your default configuration file should look::
|
||||
|
||||
from test_project.controllers.root import RootController
|
||||
|
||||
@@ -188,8 +130,8 @@ This is how your default configuration file should look like::
|
||||
app = {
|
||||
'root' : RootController(),
|
||||
'modules' : [test_project],
|
||||
'static_root' : 'public',
|
||||
'template_path' : 'test_project/templates',
|
||||
'static_root' : '%(confdir)s/public',
|
||||
'template_path' : '%(confdir)s/test_project/templates',
|
||||
'reload': True,
|
||||
'debug' : True,
|
||||
'errors' : {
|
||||
@@ -206,28 +148,21 @@ This is how your default configuration file should look like::
|
||||
# pecan.conf
|
||||
|
||||
|
||||
.. note::
|
||||
If you named your project something other than *test_project*
|
||||
you should see that same name above instead.
|
||||
|
||||
|
||||
**Nothing** in the configuration file above is actually required for Pecan to
|
||||
be able to run. If you fail to provide some values Pecan will fill in the
|
||||
missing things it needs to run.
|
||||
run. If you fail to provide some values, Pecan will fill in the missing things
|
||||
it needs to run.
|
||||
|
||||
You also get the ability to set your own configurations as dictionaries and you
|
||||
get a commented out example on how to do that.
|
||||
You can also add your own configuration as dictionaries.
|
||||
|
||||
We are not going to explain much more about configuration here, if you need
|
||||
more specific details, go to the :ref:`Configuration` section.
|
||||
For more specific documentation on configuration, see the :ref:`Configuration`
|
||||
section.
|
||||
|
||||
|
||||
Root Controller
|
||||
---------------
|
||||
The Root Controller is the main point of contact between your application and
|
||||
the framework.
|
||||
The Root Controller is the root of your application.
|
||||
|
||||
This is how it looks from the project template::
|
||||
This is how it looks in the project template::
|
||||
|
||||
from pecan import expose, request
|
||||
from formencode import Schema, validators as v
|
||||
@@ -259,35 +194,33 @@ This is how it looks from the project template::
|
||||
|
||||
|
||||
|
||||
Here you can specify other classes if you need to do so later on your project,
|
||||
but for now we have an *index* method and a *handle_form* one.
|
||||
You can specify additional classes if you need to do so, but for now we have an
|
||||
*index* and *handle_form* method.
|
||||
|
||||
**index**: Is *exposed* via the decorator ``@expose`` (that in turn uses the
|
||||
``index.html`` file) as the root of the application, so anything that hits
|
||||
the root of you application will touch this method.
|
||||
**index**: is *exposed* via the decorator ``@expose`` (which in turn uses the
|
||||
``index.html`` template) at the root of the application (http://127.0.0.1:8080/),
|
||||
so anything that hits the root of your application will touch this method.
|
||||
|
||||
What your index method returns is a dictionary that is received by the template
|
||||
engine and translated into valid HTML.
|
||||
Notice that the index method returns a dictionary - this dictionary is used as
|
||||
a namespace to render the specified template (``index.html``) into HTML.
|
||||
|
||||
Since we are doing some validation and want to pass any errors we might get to
|
||||
the template, we set ``errors`` to receive anything that
|
||||
``request.validation_errors`` returns.
|
||||
Since we are performing form validation and want to pass any errors we might
|
||||
get to the template, we set ``errors`` to receive form validation errors that
|
||||
may exist in ``request.validation_errors``.
|
||||
|
||||
|
||||
**handle_form**: It receives 2 arguments (*name* and *age*) that are validated
|
||||
through the *SampleForm* schema class.
|
||||
**handle_form**: receives 2 arguments (*name* and *age*) that are validated
|
||||
through the *SampleForm* schema.
|
||||
|
||||
The ``error_handler`` has been set to index, this means that when errors are raised
|
||||
they will be sent to the index controller so it returns them to the template.
|
||||
The ``error_handler`` has been set to index. This means that when errors are
|
||||
raised, they will be sent to the index controller and rendered through its
|
||||
template.
|
||||
|
||||
**error**: Finally, we have the error controller that allows you application to
|
||||
custom display any possible errors that you might want to display.
|
||||
**error**: Finally, we have the error controller that allows your application to
|
||||
display custom pages for certain HTTP errors (404, etc...).
|
||||
|
||||
Application Interaction
|
||||
-----------------------
|
||||
If you still have your application running and you visit your browser, you should
|
||||
see a nice page with some information about Pecan and a form so you can play a bit
|
||||
with.
|
||||
|
||||
This is very basic but it will give you the grounds necessary to build your application
|
||||
and understand some of the features the framework packs.
|
||||
If you still have your application running and you visit it in your browser,
|
||||
you should see a page with some information about Pecan and a form so you can
|
||||
play a bit.
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
.. _session:
|
||||
|
||||
Working with Sessions and User Authentication
|
||||
=============
|
||||
Out of the box, Pecan provides no opinionated support for managing user sessions,
|
||||
but it's easy to hook into your session framework of choice with minimal
|
||||
effort.
|
||||
|
||||
This article details best practices for integrating the popular session
|
||||
framework, `Beaker <http://beaker.groovie.org>`_, into your Pecan project.
|
||||
|
||||
Setting up Session Management
|
||||
----------------
|
||||
There are several approaches that can be taken to set up session management.
|
||||
One approach is WSGI middleware. Another is Pecan :ref:`hooks`.
|
||||
|
||||
Here's an example of wrapping your WSGI application with Beaker's
|
||||
``SessionMiddleware`` in your project's `app.py`::
|
||||
|
||||
from pecan import conf, make_app
|
||||
from beaker import SessionMiddleware
|
||||
from test_project import model
|
||||
|
||||
app = make_app(
|
||||
...
|
||||
)
|
||||
app = SessionMiddleware(app, conf.beaker)
|
||||
|
||||
...and a corresponding dictionary in your configuration file::
|
||||
|
||||
beaker = {
|
||||
'session.key' : 'sessionkey',
|
||||
'session.type' : 'cookie',
|
||||
'session.validate_key' : '05d2175d1090e31f42fa36e63b8d2aad',
|
||||
'__force_dict__' : True
|
||||
}
|
||||
|
||||
@@ -175,9 +175,6 @@ def import_module(conf):
|
||||
:param conf: The string to the configuration. Automatically strips off ".py" file extensions.
|
||||
'''
|
||||
|
||||
if conf.endswith('.py'):
|
||||
conf = conf[:-3]
|
||||
|
||||
if '.' in conf:
|
||||
parts = conf.split('.')
|
||||
name = '.'.join(parts[:-1])
|
||||
@@ -207,15 +204,12 @@ def initconf():
|
||||
|
||||
def set_config(name):
|
||||
'''
|
||||
Updates the global configuration from a path or filename.
|
||||
Updates the global configuration a filename.
|
||||
|
||||
:param name: Path or filename, as a string.
|
||||
:param name: filename, as a string.
|
||||
'''
|
||||
|
||||
if '/' in name:
|
||||
_runtime_conf.update(conf_from_file(name))
|
||||
else:
|
||||
_runtime_conf.update_with_module(name)
|
||||
|
||||
_runtime_conf.update(conf_from_file(name))
|
||||
|
||||
|
||||
_runtime_conf = initconf()
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
from pecan import conf
|
||||
|
||||
def init_model():
|
||||
# Read and parse database bindings from pecan.conf
|
||||
pass
|
||||
"""
|
||||
This is a stub method which is called at application startup time.
|
||||
|
||||
If you need to bind to a parse database configuration, set up tables or
|
||||
ORM classes, or perform any database initialization, this is the
|
||||
recommended place to do it.
|
||||
|
||||
For more information working with databases, and some common recipes,
|
||||
see http://pecan.readthedocs.org/en/latest/databases.html
|
||||
"""
|
||||
pass
|
||||
|
||||
@@ -108,14 +108,6 @@ class TestConf(TestCase):
|
||||
configuration.set_config(path)
|
||||
assert list(_runtime_conf.server) == list(configuration.initconf().server)
|
||||
|
||||
def test_config_set_from_module(self):
|
||||
configuration.set_config('config')
|
||||
self.assertEqual(_runtime_conf.server.host, '1.1.1.1')
|
||||
|
||||
def test_config_set_from_module_with_extension(self):
|
||||
configuration.set_config('config.py')
|
||||
self.assertEqual(_runtime_conf.server.host, '1.1.1.1')
|
||||
|
||||
def test_config_dir(self):
|
||||
if sys.version_info >= (2, 6):
|
||||
conf = configuration.Config({})
|
||||
|
||||
Reference in New Issue
Block a user