summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorMichael Merickel <michael@digitalartefacts.com>2013-10-19 02:04:02 -0500
committerMichael Merickel <michael@digitalartefacts.com>2013-10-19 02:04:02 -0500
commitc137eccf36aed3200592da0b170bc7f3ba1313b6 (patch)
tree3599f91b8c4863613be977ce847e5739b1f34804 /docs
parent8385569b371a2586acf1680937ca656136c2502c (diff)
parent3acee31f86bcde8abbb4e63715afc5ca67976eaf (diff)
downloadpyramid-c137eccf36aed3200592da0b170bc7f3ba1313b6.tar.gz
pyramid-c137eccf36aed3200592da0b170bc7f3ba1313b6.tar.bz2
pyramid-c137eccf36aed3200592da0b170bc7f3ba1313b6.zip
Merge branch 'master' into feature.signed-cookie-session
Diffstat (limited to 'docs')
-rw-r--r--docs/conf.py101
-rw-r--r--docs/glossary.rst32
-rw-r--r--docs/narr/commandline.rst11
-rw-r--r--docs/narr/install.rst12
-rw-r--r--docs/narr/introduction.rst34
-rw-r--r--docs/narr/project.rst110
-rw-r--r--docs/narr/renderers.rst22
-rw-r--r--docs/narr/sessions.rst42
-rw-r--r--docs/narr/traversal.rst30
-rw-r--r--docs/narr/upgrading.rst2
-rw-r--r--docs/quick_tour.rst23
-rw-r--r--docs/quick_tour/jinja2/hello_world.jinja23
-rw-r--r--docs/quick_tutorial/databases.rst11
-rw-r--r--docs/quick_tutorial/debugtoolbar/tutorial/__init__.py4
-rw-r--r--docs/quick_tutorial/ini.rst2
-rw-r--r--docs/quick_tutorial/jinja2.rst7
-rw-r--r--docs/quick_tutorial/jinja2/development.ini1
-rw-r--r--docs/quick_tutorial/jinja2/tutorial/__init__.py1
-rw-r--r--docs/quick_tutorial/more_view_classes.rst2
-rw-r--r--docs/quick_tutorial/requirements.rst26
-rw-r--r--docs/quick_tutorial/retail_forms/development.ini41
-rw-r--r--docs/quick_tutorial/retail_forms/setup.py15
-rw-r--r--docs/quick_tutorial/retail_forms/tutorial/__init__.py13
-rw-r--r--docs/quick_tutorial/retail_forms/tutorial/tests.py36
-rw-r--r--docs/quick_tutorial/retail_forms/tutorial/views.py96
-rw-r--r--docs/quick_tutorial/retail_forms/tutorial/wiki_view.pt19
-rw-r--r--docs/quick_tutorial/retail_forms/tutorial/wikipage_addedit.pt37
-rw-r--r--docs/quick_tutorial/retail_forms/tutorial/wikipage_view.pt17
-rw-r--r--docs/quick_tutorial/sessions.rst4
-rw-r--r--docs/quick_tutorial/unit_testing.rst2
-rw-r--r--docs/quick_tutorial/views.rst2
-rw-r--r--docs/tutorials/wiki/src/tests/tutorial/tests.py24
-rw-r--r--docs/tutorials/wiki2/src/authorization/tutorial/scripts/initializedb.py2
-rw-r--r--docs/tutorials/wiki2/src/authorization/tutorial/tests.py8
-rw-r--r--docs/tutorials/wiki2/src/authorization/tutorial/views.py4
-rw-r--r--docs/tutorials/wiki2/src/models/tutorial/scripts/initializedb.py2
-rw-r--r--docs/tutorials/wiki2/src/tests/tutorial/scripts/initializedb.py2
-rw-r--r--docs/tutorials/wiki2/src/tests/tutorial/tests.py8
-rw-r--r--docs/tutorials/wiki2/src/tests/tutorial/views.py4
-rw-r--r--docs/tutorials/wiki2/src/views/tutorial/scripts/initializedb.py2
-rw-r--r--docs/tutorials/wiki2/src/views/tutorial/tests.py8
-rw-r--r--docs/tutorials/wiki2/src/views/tutorial/views.py4
42 files changed, 516 insertions, 310 deletions
diff --git a/docs/conf.py b/docs/conf.py
index ee852aa51..a447c9968 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -73,9 +73,6 @@ intersphinx_mapping = {
'http://docs.pylonsproject.org/projects/deform/en/latest',
None),
'sqla': ('http://docs.sqlalchemy.org/en/latest', None),
- 'beaker': (
- 'http://docs.pylonsproject.org/projects/pyramid_beaker/en/latest',
- None),
'who': ('http://docs.repoze.org/who/latest', None),
'python': ('http://docs.python.org', None),
'python3': ('http://docs.python.org/3', None),
@@ -122,39 +119,19 @@ release = version
# Else, today_fmt is used as the format for a strftime call.
today_fmt = '%B %d, %Y'
-# List of documents that shouldn't be included in the build.
-#unused_docs = []
-
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
exclude_patterns = ['_themes/README.rst', ]
-# List of directories, relative to source directories, that shouldn't be searched
-# for source files.
-#exclude_dirs = []
-
-# The reST default role (used for this markup: `text`) to use for all documents.
-#default_role = None
-
-# If true, '()' will be appended to :func: etc. cross-reference text.
-#add_function_parentheses = True
-
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
add_module_names = False
-# If true, sectionauthor and moduleauthor directives will be shown in the
-# output. They are ignored by default.
-#show_authors = False
-
# The name of the Pygments (syntax highlighting) style to use.
#pygments_style = book and 'bw' or 'tango'
if book:
pygments_style = 'bw'
-# The default language to highlight source code in.
-#highlight_language = 'guess'
-
# Options for HTML output
# -----------------------
@@ -173,49 +150,17 @@ if 'sphinx-build' in ' '.join(sys.argv): # protect against dumb importers
sys.path.append(os.path.abspath('_themes'))
- parent = os.path.dirname(os.path.dirname(__file__))
- sys.path.append(os.path.abspath(parent))
- wd = os.getcwd()
- os.chdir(parent)
- os.system('%s setup.py test -q' % sys.executable)
- os.chdir(wd)
-
- for item in os.listdir(parent):
- if item.endswith('.egg'):
- sys.path.append(os.path.join(parent, item))
-
html_theme_path = ['_themes']
html_theme = 'pyramid'
html_theme_options = dict(
github_url='https://github.com/Pylons/pyramid',
in_progress='true',
)
-# The style sheet to use for HTML and HTML Help pages. A file of that name
-# must exist either in Sphinx' static/ path, or in one of the custom paths
-# given in html_static_path.
-#html_style = 'pyramid.css'
# The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation".
html_title = 'The Pyramid Web Framework v%s' % release
-# A shorter title for the navigation bar. Default is the same as html_title.
-#html_short_title = 'Home'
-
-# The name of an image file (within the static path) to place at the top of
-# the sidebar.
-#html_logo = '_static/pyramid.png'
-
-# The name of an image file (within the static path) to use as favicon of the
-# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
-# pixels large.
-#html_favicon = '_static/pyramid.ico'
-
-# Add any paths that contain custom static files (such as style sheets) here,
-# relative to this directory. They are copied after the builtin static files,
-# so a file named "default.css" will overwrite the builtin "default.css".
-#html_static_path = ['_static']
-
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
html_last_updated_fmt = '%b %d, %Y'
@@ -224,33 +169,6 @@ html_last_updated_fmt = '%b %d, %Y'
# typographically correct entities.
html_use_smartypants = False # people use cutnpaste in some places
-# Custom sidebar templates, maps document names to template names.
-#html_sidebars = {}
-
-# Additional templates that should be rendered to pages, maps page names to
-# template names.
-#html_additional_pages = {}
-
-# If false, no module index is generated.
-#html_use_modindex = True
-
-# If false, no index is generated.
-#html_use_index = True
-
-# If true, the index is split into individual pages for each letter.
-#html_split_index = False
-
-# If true, the reST sources are included in the HTML build as _sources/<name>.
-#html_copy_source = True
-
-# If true, an OpenSearch description file will be output, and all pages will
-# contain a <link> tag referring to it. The value of this option must be the
-# base URL from which the finished HTML is served.
-#html_use_opensearch = ''
-
-# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml").
-#html_file_suffix = ''
-
# Output file base name for HTML help builder.
htmlhelp_basename = 'pyramid'
@@ -273,20 +191,10 @@ latex_documents = [
'Chris McDonough', 'manual'),
]
-# The name of an image file (relative to this directory) to place at the top of
-# the title page.
-#latex_logo = '_static/pylons_small.png'
-
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
latex_use_parts = True
-# Additional stuff for the LaTeX preamble.
-#latex_preamble = ''
-
-# Documents to append as an appendix to all manuals.
-#latex_appendices = []
-
# If false, no module index is generated.
latex_use_modindex = False
@@ -529,13 +437,6 @@ epub_identifier = '0615445675'
# A unique identification for the text.
epub_uid = 'The Pyramid Web Framework, Version %s' \
% release
-# HTML files that should be inserted before the pages created by sphinx.
-# The format is a list of tuples containing the path and title.
-#epub_pre_files = []
-
-# HTML files shat should be inserted after the pages created by sphinx.
-# The format is a list of tuples containing the path and title.
-#epub_post_files = []
# A list of files that should not be packed into the epub file.
epub_exclude_files = ['_static/opensearch.xml', '_static/doctools.js',
@@ -545,3 +446,5 @@ epub_exclude_files = ['_static/opensearch.xml', '_static/doctools.js',
# The depth of the table of contents in toc.ncx.
epub_tocdepth = 3
+
+# For a list of all settings, visit http://sphinx-doc.org/config.html
diff --git a/docs/glossary.rst b/docs/glossary.rst
index 7dc69c7c4..406b81778 100644
--- a/docs/glossary.rst
+++ b/docs/glossary.rst
@@ -505,15 +505,20 @@ Glossary
available as its ``__parent__`` attribute.
root factory
- The "root factory" of a :app:`Pyramid` application is called
- on every request sent to the application. The root factory
- returns the traversal root of an application. It is
- conventionally named ``get_root``. An application may supply a
- root factory to :app:`Pyramid` during the construction of a
- :term:`Configurator`. If a root factory is not supplied, the
- application uses a default root object. Use of the default root
- object is useful in application which use :term:`URL dispatch` for
- all URL-to-view code mappings.
+ The "root factory" of a :app:`Pyramid` application is called on every
+ request sent to the application. The root factory returns the traversal
+ root of an application. It is conventionally named ``get_root``. An
+ application may supply a root factory to :app:`Pyramid` during the
+ construction of a :term:`Configurator`. If a root factory is not
+ supplied, the application creates a default root object using the
+ :term:`default root factory`.
+
+ default root factory
+ If an application does not register a :term:`root factory` at Pyramid
+ configuration time, a *default* root factory is used to created the
+ default root object. Use of the default root object is useful in
+ application which use :term:`URL dispatch` for all URL-to-view code
+ mappings, and does not (knowingly) use traversal otherwise.
SQLAlchemy
`SQLAlchemy <http://www.sqlalchemy.org/>`_ is an object
@@ -1009,7 +1014,8 @@ Glossary
Green Unicorn
Aka ``gunicorn``, a fast :term:`WSGI` server that runs on UNIX under
- Python 2.6+ or Python 3.1+. See http://gunicorn.org/ for detailed information.
+ Python 2.6+ or Python 3.1+. See http://gunicorn.org/ for detailed
+ information.
predicate factory
A callable which is used by a third party during the registration of a
@@ -1021,3 +1027,9 @@ Glossary
A Python :term:`distribution` that uses Pyramid's extensibility
to plug into a Pyramid application and provide extra,
configurable services.
+
+ pyramid_redis_sessions
+ A package by Eric Rasmussen which allows you to store Pyramid session
+ data in a Redis database. See
+ https://pypi.python.org/pypi/pyramid_redis_sessions for more information.
+
diff --git a/docs/narr/commandline.rst b/docs/narr/commandline.rst
index 58b9bdd21..0984b4daf 100644
--- a/docs/narr/commandline.rst
+++ b/docs/narr/commandline.rst
@@ -474,6 +474,17 @@ input of the ``prequest`` process is used as the ``POST`` body::
$ $VENV/bin/prequest -mPOST development.ini / < somefile
+Using Custom Arguments to Python when Running ``p*`` Scripts
+------------------------------------------------------------
+
+.. versionadded:: 1.5
+
+Each of Pyramid's console scripts (``pserve``, ``pviews``, etc) can be run
+directly using ``python -m``, allowing custom arguments to be sent to the
+python interpreter at runtime. For example::
+
+ python -3 -m pyramid.scripts.pserve development.ini
+
Showing All Installed Distributions and their Versions
------------------------------------------------------
diff --git a/docs/narr/install.rst b/docs/narr/install.rst
index f3f736df6..e419a8b20 100644
--- a/docs/narr/install.rst
+++ b/docs/narr/install.rst
@@ -289,9 +289,9 @@ Installing :app:`Pyramid` Into the Virtual Python Environment
After you've got your virtualenv installed, you may install :app:`Pyramid`
itself using the following commands:
-.. code-block:: text
-
- $ $VENV/bin/easy_install pyramid
+.. parsed-literal::
+
+ $ $VENV/bin/easy_install "pyramid==\ |release|\ "
The ``easy_install`` command will take longer than the previous ones to
complete, as it downloads and installs a number of dependencies.
@@ -368,9 +368,9 @@ You can use Pyramid on Windows under Python 2 or 3.
#. Use ``easy_install`` to get :app:`Pyramid` and its direct dependencies
installed:
- .. code-block:: text
-
- c:\env> %VENV%\Scripts\easy_install pyramid
+ .. parsed-literal::
+
+ c:\\env> %VENV%\\Scripts\\easy_install "pyramid==\ |release|\ "
What Gets Installed
-------------------
diff --git a/docs/narr/introduction.rst b/docs/narr/introduction.rst
index 032f4be6b..a9c5fdfbd 100644
--- a/docs/narr/introduction.rst
+++ b/docs/narr/introduction.rst
@@ -176,8 +176,13 @@ static file server in production without changing any code.
Example: :ref:`static_assets_section`.
-Debug Toolbar
-~~~~~~~~~~~~~
+Fully Interactive Development
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+When developing a Pyramid application, several interactive features are
+available. Pyramid can automatically utilize changed templates when rendering
+pages and automatically restart the application to incorporate changed python
+code. Plain old ``print()`` calls used for debugging can display to a console.
Pyramid's debug toolbar comes activated when you use a Pyramid scaffold to
render a project. This toolbar overlays your application in the browser, and
@@ -321,7 +326,14 @@ assertion instead that the view returns "the right stuff" in the dictionary
it returns. You can write "real" unit tests instead of functionally testing
all of your views.
-For example, instead of:
+.. index::
+ pair: renderer; explicitly calling
+ pair: view renderer; explictly calling
+
+.. _example_render_to_response_call:
+
+For example, instead of returning a ``Response`` object from a
+``render_to_response`` call:
.. code-block:: python
:linenos:
@@ -332,7 +344,7 @@ For example, instead of:
return render_to_response('myapp:templates/mytemplate.pt', {'a':1},
request=request)
-You can do this:
+You can return a Python dictionary:
.. code-block:: python
:linenos:
@@ -405,12 +417,12 @@ Sessions
Pyramid has built-in HTTP sessioning. This allows you to associate data with
otherwise anonymous users between requests. Lots of systems do this. But
-Pyramid also allows you to plug in your own sessioning system by creating
-some code that adheres to a documented interface. Currently there is a
-binding package for the third-party Beaker sessioning system that does exactly
-this. But if you have a specialized need (perhaps you want to store your
-session data in MongoDB), you can. You can even switch between
-implementations without changing your application code.
+Pyramid also allows you to plug in your own sessioning system by creating some
+code that adheres to a documented interface. Currently there is a binding
+package for the third-party Redis sessioning system that does exactly this.
+But if you have a specialized need (perhaps you want to store your session data
+in MongoDB), you can. You can even switch between implementations without
+changing your application code.
Example: :ref:`sessions_chapter`.
@@ -777,7 +789,7 @@ automate some of the tedium away:
for method in ('GET', 'POST', 'HEAD'):
view = getattr(module, 'xhr_%s_view' % method, None)
if view is not None:
- config.add_view(view, route_name='xhr_route', xhr=True,
+ config.add_view(view, route_name='xhr_route', xhr=True,
permission='view', request_method=method)
config = Configurator()
diff --git a/docs/narr/project.rst b/docs/narr/project.rst
index f3050f805..d7292d187 100644
--- a/docs/narr/project.rst
+++ b/docs/narr/project.rst
@@ -144,9 +144,9 @@ contains no space characters, so it's wise to *avoid* a path that contains
i.e. ``My Documents``. As a result, the author, when he uses Windows, just
puts his projects in ``C:\projects``.
-.. warning::
+.. warning::
- You’ll need to avoid using ``pcreate`` to create a project with the same
+ You'll need to avoid using ``pcreate`` to create a project with the same
name as a Python standard library component. In particular, this means you
should avoid using the names ``site`` or ``test``, both of which
conflict with Python standard library packages. You should also avoid
@@ -193,10 +193,10 @@ Elided output from a run of this command on UNIX is shown below:
...
Finished processing dependencies for MyProject==0.0
-This will install a :term:`distribution` representing your project into the
-interpreter's library set so it can be found by ``import`` statements and by
-other console scripts such as ``pserve``, ``pshell``, ``proutes`` and
-``pviews``.
+This will install a :term:`distribution` representing your project
+into the virtual environment interpreter's library set so it can be
+found by ``import`` statements and by other console scripts such as
+``pserve``, ``pshell``, ``proutes`` and ``pviews``.
.. index::
single: running tests
@@ -243,22 +243,24 @@ Here's sample output from a test run on UNIX:
OK
-.. note::
-
- The ``-q`` option is passed to the ``setup.py test`` command to limit the
- output to a stream of dots. If you don't pass ``-q``, you'll see more
- verbose test result output (which normally isn't very useful).
-
The tests themselves are found in the ``tests.py`` module in your ``pcreate``
generated project. Within a project generated by the ``starter`` scaffold, a
single sample test exists.
+.. note::
+
+ The ``-q`` option is passed to the ``setup.py test`` command to limit the
+ output to a stream of dots. If you don't pass ``-q``, you'll see more
+ verbose test result output (which normally isn't very useful).
+
.. index::
single: running an application
single: pserve
single: reload
single: startup
+.. _running_the_project_application:
+
Running The Project Application
-------------------------------
@@ -600,6 +602,8 @@ server which listens on TCP port 6543. It is configured to listen on all
interfaces (``0.0.0.0``). This means that any remote system which has TCP
access to your system can see your Pyramid application.
+.. _MyProject_ini_logging:
+
The sections that live between the markers ``# Begin logging configuration``
and ``# End logging configuration`` represent Python's standard library
:mod:`logging` module configuration for your application. The sections
@@ -696,11 +700,11 @@ testing, packaging, and distributing your application.
.. note::
- ``setup.py`` is the de facto standard which Python developers use to
- distribute their reusable code. You can read more about ``setup.py`` files
- and their usage in the `Setuptools documentation
- <http://peak.telecommunity.com/DevCenter/setuptools>`_ and `The
- Hitchhiker's Guide to Packaging <http://guide.python-distribute.org/>`_.
+ ``setup.py`` is the de facto standard which Python developers use to
+ distribute their reusable code. You can read more about ``setup.py`` files
+ and their usage in the `Setuptools documentation
+ <http://peak.telecommunity.com/DevCenter/setuptools>`_ and `The
+ Hitchhiker's Guide to Packaging <http://guide.python-distribute.org/>`_.
Our generated ``setup.py`` looks like this:
@@ -871,31 +875,48 @@ specification` that specifies the ``mytemplate.pt`` file within the
``templates`` directory of the ``myproject`` package. The asset
specification could have also been specified as
``myproject:templates/mytemplate.pt``; the leading package name and colon is
-optional. The template file it actually points to is a :term:`Chameleon` ZPT
-template file.
+optional. The template file pointed to is a :term:`Chameleon` ZPT
+template file (``templates/my_template.pt``).
This view callable function is handed a single piece of information: the
:term:`request`. The *request* is an instance of the :term:`WebOb`
``Request`` class representing the browser's request to our server.
-This view returns a dictionary. When this view is invoked, a
-:term:`renderer` converts the dictionary returned by the view into HTML, and
-returns the result as the :term:`response`. This view is configured to
-invoke a renderer which uses a :term:`Chameleon` ZPT template
-(``templates/my_template.pt``).
-
-See :ref:`views_which_use_a_renderer` for more information about how views,
-renderers, and templates relate and cooperate.
-
-.. note:: Because our ``development.ini`` has a ``pyramid.reload_templates =
- true`` directive indicating that templates should be reloaded when
- they change, you won't need to restart the application server to
- see changes you make to templates. During development, this is
- handy. If this directive had been ``false`` (or if the directive
- did not exist), you would need to restart the application server
- for each template change. For production applications, you should
- set your project's ``pyramid.reload_templates`` to ``false`` to increase
- the speed at which templates may be rendered.
+This view is configured to invoke a :term:`renderer` on a template. The
+dictionary the view returns (on line 6) provides the value the renderer
+substitutes into the template when generating HTML. The renderer then
+returns the HTML in a :term:`response`.
+
+.. note:: Dictionaries provide values to :term:`template`\s.
+
+.. note:: When the application is run with the scaffold's :ref:`default
+ development.ini <MyProject_ini>` configuration :ref:`logging is set up
+ <MyProject_ini_logging>` to aid debugging. If an exception is raised,
+ uncaught tracebacks are displayed after the startup messages on :ref:`the
+ console running the server <running_the_project_application>`. Also
+ ``print()`` statements may be inserted into the application for debugging
+ to send output to this console.
+
+.. note:: ``development.ini`` has a setting that controls how templates are
+ reloaded, ``pyramid.reload_templates``.
+
+ - When set to ``True`` (as in the scaffold ``development.ini``) changed
+ templates automatically reload without a server restart. This is
+ convenient while developing, but slows template rendering speed.
+
+ - When set to ``False`` (the default value), changing templates requires
+ a server restart to reload them. Production applications should use
+ ``pyramid.reload_templates = False``.
+
+.. seealso:: See also :ref:`views_which_use_a_renderer` for more information
+ about how views, renderers, and templates relate and cooperate.
+
+.. seealso:: Pyramid can also dynamically reload changed Python files. For
+ more on this see :ref:`reloading_code`.
+
+.. seealso:: The :ref:`debug_toolbar` provides interactive access to your
+ application's internals and, should an exception occur, allows interactive
+ access to traceback execution stack frames from the Python interpreter.
.. index::
single: static directory
@@ -971,12 +992,15 @@ named ``views`` instead of within a single ``views.py`` file, you might:
- Create a ``views`` directory inside your ``myproject`` package directory
(the same directory which holds ``views.py``).
-- *Move* the existing ``views.py`` file to a file inside the new ``views``
- directory named, say, ``blog.py``.
+- Create a file within the new ``views`` directory named ``__init__.py``. (It
+ can be empty. This just tells Python that the ``views`` directory is a
+ *package*.)
-- Create a file within the new ``views`` directory named ``__init__.py`` (it
- can be empty, this just tells Python that the ``views`` directory is a
- *package*.
+- *Move* the content from the existing ``views.py`` file to a file inside the
+ new ``views`` directory named, say, ``blog.py``. Because the ``templates``
+ directory remains in the ``myproject`` package, the template :term:`asset
+ specification` values in ``blog.py`` must now be fully qualified with the
+ project's package name (``myproject:templates/blog.pt``).
You can then continue to add view callable functions to the ``blog.py``
module, but you can also add other ``.py`` files which contain view callable
@@ -1025,7 +1049,7 @@ server. Waitress is a server that is suited for development and light
production usage. It's not the fastest nor the most featureful WSGI server.
Instead, its main feature is that it works on all platforms that Pyramid
needs to run on, making it a good choice as a default server from the
-perspective of Pyramid's developers.
+perspective of Pyramid's developers.
Any WSGI server is capable of running a :app:`Pyramid` application. But we
suggest you stick with the default server for development, and that you wait
diff --git a/docs/narr/renderers.rst b/docs/narr/renderers.rst
index 3059aef35..740c81555 100644
--- a/docs/narr/renderers.rst
+++ b/docs/narr/renderers.rst
@@ -49,15 +49,19 @@ Writing View Callables Which Use a Renderer
-------------------------------------------
As we've seen, a view callable needn't always return a Response object.
-Instead, it may return an arbitrary Python object, with the expectation
-that a :term:`renderer` will convert that object into a response instance on
-your behalf. Some renderers use a templating system; other renderers use
-object serialization techniques.
-
-View configuration can vary the renderer associated with a view callable via
-the ``renderer`` attribute. For example, this call to
-:meth:`~pyramid.config.Configurator.add_view` associates the ``json`` renderer
-with a view callable:
+Instead, it may return an arbitrary Python object, with the expectation that
+a :term:`renderer` will convert that object into a response instance on your
+behalf. Some renderers use a templating system; other renderers use object
+serialization techniques. In practice, renderers obtain application data
+values from Python dictionaries so, in practice, view callables which use
+renderers return Python dictionaries.
+
+View callables can :ref:`explicitly call <example_render_to_response_call>`
+renderers, but typically don't. Instead view configuration declares the
+renderer used to render a view callable's results. This is done with the
+``renderer`` attribute. For example, this call to
+:meth:`~pyramid.config.Configurator.add_view` associates the ``json``
+renderer with a view callable:
.. code-block:: python
diff --git a/docs/narr/sessions.rst b/docs/narr/sessions.rst
index 1d914f9ea..fb5035373 100644
--- a/docs/narr/sessions.rst
+++ b/docs/narr/sessions.rst
@@ -98,6 +98,11 @@ example:
else:
return Response('Fred was not in the session')
+The first time this view is invoked produces ``Fred was not in the
+session``. Subsequent invocations produce ``Fred was in the
+session``, assuming of course that the client side maintains the
+session's identity across multiple requests.
+
You can use a session much like a Python dictionary. It supports all
dictionary methods, along with some extra attributes, and methods.
@@ -145,8 +150,6 @@ Some gotchas:
you've changed sessioning data.
.. index::
- single: pyramid_beaker
- single: Beaker
single: pyramid_redis_sessions
single: session factory (alternates)
@@ -155,19 +158,10 @@ Some gotchas:
Using Alternate Session Factories
---------------------------------
-At the time of this writing, exactly two alternate session factories
-exist.
-
-The first is named ``pyramid_redis_sessions``. It can be downloaded from PyPI.
-It uses Redis as a backend. It is the recommended persistent session solution
-at the time of this writing.
-
-The second is named ``pyramid_beaker``. This is a session factory that uses the
-`Beaker <http://beaker.groovie.org/>`_ library as a backend. Beaker has
-support for file-based sessions, database based sessions, and encrypted
-cookie-based sessions. See `the pyramid_beaker documentation
-<http://docs.pylonsproject.org/projects/pyramid_beaker/en/latest/>`_ for more
-information about ``pyramid_beaker``.
+At the time of this writing, exactly one project-endorsed alternate session
+factory exists named :term:`pyramid_redis_sessions`. It can be downloaded from
+PyPI. It uses the Redis database as a backend. It is the recommended
+persistent session solution at the time of this writing.
.. index::
single: session factory (custom)
@@ -368,25 +362,27 @@ Or, include it as a header in a jQuery AJAX request:
The handler for the URL that receives the request
should then require that the correct CSRF token is supplied.
-Using the ``session.check_csrf_token`` Method
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Checking CSRF Tokens Manually
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In request handling code, you can check the presence and validity of a CSRF
-token with ``session.check_csrf_token(request)``. If the token is valid,
-it will return True, otherwise it will raise ``HTTPBadRequest``.
+token with :func:`pyramid.session.check_csrf_token(request)``. If the token is
+valid, it will return ``True``, otherwise it will raise ``HTTPBadRequest``.
+Optionally, you can specify ``raises=False`` to have the check return ``False``
+instead of raising an exception.
By default, it checks for a GET or POST parameter named ``csrf_token`` or a
header named ``X-CSRF-Token``.
.. code-block:: python
- def myview(request):
- session = request.session
+ from pyramid.session import check_csrf_token
+ def myview(request):
# Require CSRF Token
- session.check_csrf_token(request):
+ check_csrf_token(request)
- ...
+ # ...
.. index::
single: session.new_csrf_token
diff --git a/docs/narr/traversal.rst b/docs/narr/traversal.rst
index a60c5ba56..454bb5620 100644
--- a/docs/narr/traversal.rst
+++ b/docs/narr/traversal.rst
@@ -146,35 +146,15 @@ refer to a root factory defined in a different module.
If no :term:`root factory` is passed to the :app:`Pyramid`
:term:`Configurator` constructor, or if the ``root_factory`` value
-specified is ``None``, a *default* root factory is used. The default
+specified is ``None``, a :term:`default root factory` is used. The default
root factory always returns a resource that has no child resources; it
is effectively empty.
Usually a root factory for a traversal-based application will be more
-complicated than the above ``Root`` class; in particular it may be
-associated with a database connection or another persistence mechanism.
-
-.. sidebar:: Emulating the Default Root Factory
-
- For purposes of understanding the default root factory better, we'll note
- that you can emulate the default root factory by using this code as an
- explicit root factory in your application setup:
-
- .. code-block:: python
- :linenos:
-
- class Root(object):
- def __init__(self, request):
- pass
-
- config = Configurator(root_factory=Root)
-
- The default root factory is just a really stupid object that has no
- behavior or state. Using :term:`traversal` against an application that
- uses the resource tree supplied by the default root resource is not very
- interesting, because the default root resource has no children. Its
- availability is more useful when you're developing an application using
- :term:`URL dispatch`.
+complicated than the above ``Root`` class; in particular it may be associated
+with a database connection or another persistence mechanism. The above
+``Root`` class is analogous to the default root factory present in Pyramid. The
+default root factory is very simple and not very useful.
.. note::
diff --git a/docs/narr/upgrading.rst b/docs/narr/upgrading.rst
index ca6dc565b..64343ca3e 100644
--- a/docs/narr/upgrading.rst
+++ b/docs/narr/upgrading.rst
@@ -150,7 +150,7 @@ do things the newer way:
.. code-block:: python
:linenos:
- from pyramid.view. import view_config
+ from pyramid.view import view_config
from pyramid.static import static_view
myview = static_view('static', 'static', use_subpath=True)
diff --git a/docs/quick_tour.rst b/docs/quick_tour.rst
index 434dbdad5..2db18c8a7 100644
--- a/docs/quick_tour.rst
+++ b/docs/quick_tour.rst
@@ -17,26 +17,26 @@ Pyramid is a breeze. Unfortunately "standard" is not so simple in Python.
For this Quick Tour, it means:
`Python <http://www.python.org/download/releases/>`_, a
`virtual environment <http://docs.python.org/dev/library/venv.html>`_
-(or `virtualenv for Python 2.7 <https://pypi.python.org/pypi/virtualenv>`_,
+(or `virtualenv for Python 2.7 <https://pypi.python.org/pypi/virtualenv>`_),
and `setuptools <https://pypi.python.org/pypi/setuptools/>`_.
As an example, for Python 3.3+ on Linux:
-.. code-block:: bash
+.. parsed-literal::
$ pyvenv env33
$ wget https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setup.py -O - | env33/bin/python
- $ env33/bin/easy_install pyramid
+ $ env33/bin/easy_install "pyramid==\ |release|\ "
For Windows:
-.. code-block:: posh
+.. parsed-literal::
# Use your browser to download:
# https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setup.py
- c:\> c:\Python33\python -m venv env33
- c:\> env33\Scripts\python ez_setup.py
- c:\> env33\Scripts\easy_install pyramid
+ c:\\> c:\\Python33\\python -m venv env33
+ c:\\> env33\\Scripts\\python ez_setup.py
+ c:\\> env33\\Scripts\\easy_install "pyramid==\ |release|\ "
Of course Pyramid runs fine on Python 2.6+, as do the examples in this
*Quick Tour*. We're just showing Python 3 a little love (Pyramid had
@@ -297,7 +297,7 @@ The only change in our view...point the renderer at the ``.jinja2`` file:
Our Jinja2 template is very similar to our previous template:
.. literalinclude:: quick_tour/jinja2/hello_world.jinja2
- :language: jinja
+ :language: html
Pyramid's templating add-ons register a new kind of renderer into your
application. The renderer registration maps to different kinds of
@@ -729,8 +729,8 @@ that requires semi-permanent data to be saved. For example, a shopping
cart. This is called a :term:`session`.
Pyramid has basic built-in support for sessions, with add-ons such as
-*Beaker* (or your own custom sessioning engine) that provide richer
-session support. Let's take a look at the
+``pyramid_redis_sessions`` (or your own custom sessioning engine) that provide
+richer session support. Let's take a look at the
:doc:`built-in sessioning support <../narr/sessions>`. In our
``__init__.py`` we first import the kind of sessioning we want:
@@ -768,8 +768,7 @@ Jinja2 template:
.. seealso:: See Also:
:ref:`Quick Tutorial Sessions <qtut_sessions>`,
:ref:`sessions_chapter`, :ref:`flash_messages`,
- :ref:`session_module`, and
- :ref:`Beaker sessioning middleware <beaker:overview>`
+ :ref:`session_module`, and :term:`pyramid_redis_sessions`.
Databases
=========
diff --git a/docs/quick_tour/jinja2/hello_world.jinja2 b/docs/quick_tour/jinja2/hello_world.jinja2
index e177744b5..7a902dd3a 100644
--- a/docs/quick_tour/jinja2/hello_world.jinja2
+++ b/docs/quick_tour/jinja2/hello_world.jinja2
@@ -1,4 +1,5 @@
-<html xmlns="http://www.w3.org/1999/xhtml">
+<!DOCTYPE html>
+<html lang="en">
<head>
<title>Hello World</title>
</head>
diff --git a/docs/quick_tutorial/databases.rst b/docs/quick_tutorial/databases.rst
index 93a02ffc7..20b3cd46d 100644
--- a/docs/quick_tutorial/databases.rst
+++ b/docs/quick_tutorial/databases.rst
@@ -39,15 +39,6 @@ Objectives
Steps
=====
-.. warning::
-
- Your Python might not have SQLite bundled. If not, install it into
- your virtual environment with:
-
- .. code-block:: bash
-
- $ $VENV/bin/easy_install sphinx pysqlite
-
#. We are going to use the forms step as our starting point:
.. code-block:: bash
@@ -97,7 +88,7 @@ Steps
.. code-block:: bash
- $ initialize_tutorial_db development.ini
+ $ $VENV/bin/initialize_tutorial_db development.ini
2013-09-06 15:54:08,050 INFO [sqlalchemy.engine.base.Engine][MainThread] PRAGMA table_info("wikipages")
2013-09-06 15:54:08,050 INFO [sqlalchemy.engine.base.Engine][MainThread] ()
2013-09-06 15:54:08,051 INFO [sqlalchemy.engine.base.Engine][MainThread]
diff --git a/docs/quick_tutorial/debugtoolbar/tutorial/__init__.py b/docs/quick_tutorial/debugtoolbar/tutorial/__init__.py
index 2b4e84f30..0993b25be 100644
--- a/docs/quick_tutorial/debugtoolbar/tutorial/__init__.py
+++ b/docs/quick_tutorial/debugtoolbar/tutorial/__init__.py
@@ -3,11 +3,11 @@ from pyramid.response import Response
def hello_world(request):
- return Response('<body><h1>Hello World!</h1></body>')
+ return xResponse('<body><h1>Hello World!</h1></body>')
def main(global_config, **settings):
config = Configurator(settings=settings)
config.add_route('hello', '/')
config.add_view(hello_world, route_name='hello')
- return config.make_wsgi_app() \ No newline at end of file
+ return config.make_wsgi_app()
diff --git a/docs/quick_tutorial/ini.rst b/docs/quick_tutorial/ini.rst
index 630b1faa5..618b8e5e8 100644
--- a/docs/quick_tutorial/ini.rst
+++ b/docs/quick_tutorial/ini.rst
@@ -46,7 +46,7 @@ Steps
:linenos:
#. We can now install our project, thus generating (or re-generating) an
- "egg" at ``ini/tutorial.egg-info``:
+ "egg" at ``ini/tutorial.egg-info``:
.. code-block:: bash
diff --git a/docs/quick_tutorial/jinja2.rst b/docs/quick_tutorial/jinja2.rst
index 40d941098..44d9f635b 100644
--- a/docs/quick_tutorial/jinja2.rst
+++ b/docs/quick_tutorial/jinja2.rst
@@ -29,11 +29,10 @@ Steps
$ $VENV/bin/python setup.py develop
$ $VENV/bin/easy_install pyramid_jinja2
-#. We need to add an item to ``pyramid.includes`` in
- ``jinja2/development.ini``:
+#. We need to include ``pyramid_jinja2`` in
+ ``jinja2/tutorial/__init__.py``:
- .. literalinclude:: jinja2/development.ini
- :language: ini
+ .. literalinclude:: jinja2/tutorial/__init__.py
:linenos:
#. Our ``jinja2/tutorial/views.py`` simply changes its ``renderer``:
diff --git a/docs/quick_tutorial/jinja2/development.ini b/docs/quick_tutorial/jinja2/development.ini
index c096fa936..62e0c5123 100644
--- a/docs/quick_tutorial/jinja2/development.ini
+++ b/docs/quick_tutorial/jinja2/development.ini
@@ -3,7 +3,6 @@ use = egg:tutorial
pyramid.reload_templates = true
pyramid.includes =
pyramid_debugtoolbar
- pyramid_jinja2
[server:main]
use = egg:pyramid#wsgiref
diff --git a/docs/quick_tutorial/jinja2/tutorial/__init__.py b/docs/quick_tutorial/jinja2/tutorial/__init__.py
index 013d4538f..1f6783c06 100644
--- a/docs/quick_tutorial/jinja2/tutorial/__init__.py
+++ b/docs/quick_tutorial/jinja2/tutorial/__init__.py
@@ -3,6 +3,7 @@ from pyramid.config import Configurator
def main(global_config, **settings):
config = Configurator(settings=settings)
+ config.include('pyramid_jinja2')
config.add_route('home', '/')
config.add_route('hello', '/howdy')
config.scan('.views')
diff --git a/docs/quick_tutorial/more_view_classes.rst b/docs/quick_tutorial/more_view_classes.rst
index 2792869ac..21b353b7c 100644
--- a/docs/quick_tutorial/more_view_classes.rst
+++ b/docs/quick_tutorial/more_view_classes.rst
@@ -166,7 +166,7 @@ Extra Credit
#. The ``edit`` and ``delete`` views are both submitted to with
``POST``. Why does the ``edit`` view configuration not catch the
- the ``POST`` used by ``delete``?
+ ``POST`` used by ``delete``?
#. We used Python ``@property`` on ``full_name``. If we reference this
many times in a template or view code, it would re-compute this
diff --git a/docs/quick_tutorial/requirements.rst b/docs/quick_tutorial/requirements.rst
index df63ff912..234e4aa0d 100644
--- a/docs/quick_tutorial/requirements.rst
+++ b/docs/quick_tutorial/requirements.rst
@@ -94,23 +94,23 @@ and where our virtual environment will reside:
Final directory structure.
-The commands to do so are as follows:
+For Linux, the commands to do so are as follows:
.. code-block:: bash
# Mac and Linux
$ cd ~
- $ mkdir projects
- $ cd projects
- $ mkdir quick_tutorial
- $ cd quick_tutorial
+ $ mkdir -p projects/quick_tutorial
+ $ cd projects/quick_tutorial
+
+For Windows:
+
+.. code-block:: posh
# Windows
c:\> cd \
- c:\> mkdir projects
- c:\> cd projects
- c:\> mkdir quick_tutorial
- c:\> cd quick_tutorial
+ c:\> mkdir projects\quick_tutorial
+ c:\> cd projects\quick_tutorial
In the above figure, your user home directory is represented by ``~``. In
your home directory, all of your projects are in the ``projects`` directory.
@@ -208,13 +208,13 @@ Install Pyramid
We have our Python standard prerequisites out of the way. The Pyramid
part is pretty easy:
-.. code-block:: bash
+.. parsed-literal::
# Mac and Linux
- $ $VENV/bin/easy_install pyramid
+ $ $VENV/bin/easy_install "pyramid==\ |release|\ "
# Windows
- c:\> %VENV%\Scripts\easy_install pyramid
+ c:\\> %VENV%\\Scripts\\easy_install "pyramid==\ |release|\ "
Our Python virtual environment now has the Pyramid software available.
@@ -226,7 +226,7 @@ during this tutorial:
# Mac and Linux
$ $VENV/bin/easy_install nose webtest deform sqlalchemy \
pyramid_chameleon pyramid_debugtoolbar waitress \
- pyramid_jinja2 pyramid_tm zope.sqlalchemy pysqlite
+ pyramid_jinja2 pyramid_tm zope.sqlalchemy
# Windows
c:\> %VENV%\Scripts\easy_install nose webtest deform sqlalchemy pyramid_chameleon
diff --git a/docs/quick_tutorial/retail_forms/development.ini b/docs/quick_tutorial/retail_forms/development.ini
new file mode 100644
index 000000000..62e0c5123
--- /dev/null
+++ b/docs/quick_tutorial/retail_forms/development.ini
@@ -0,0 +1,41 @@
+[app:main]
+use = egg:tutorial
+pyramid.reload_templates = true
+pyramid.includes =
+ pyramid_debugtoolbar
+
+[server:main]
+use = egg:pyramid#wsgiref
+host = 0.0.0.0
+port = 6543
+
+# Begin logging configuration
+
+[loggers]
+keys = root, tutorial
+
+[logger_tutorial]
+level = DEBUG
+handlers =
+qualname = tutorial
+
+[handlers]
+keys = console
+
+[formatters]
+keys = generic
+
+[logger_root]
+level = INFO
+handlers = console
+
+[handler_console]
+class = StreamHandler
+args = (sys.stderr,)
+level = NOTSET
+formatter = generic
+
+[formatter_generic]
+format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s
+
+# End logging configuration
diff --git a/docs/quick_tutorial/retail_forms/setup.py b/docs/quick_tutorial/retail_forms/setup.py
new file mode 100644
index 000000000..361ade013
--- /dev/null
+++ b/docs/quick_tutorial/retail_forms/setup.py
@@ -0,0 +1,15 @@
+from setuptools import setup
+
+requires = [
+ 'pyramid',
+ 'pyramid_chameleon',
+ 'deform'
+]
+
+setup(name='tutorial',
+ install_requires=requires,
+ entry_points="""\
+ [paste.app_factory]
+ main = tutorial:main
+ """,
+) \ No newline at end of file
diff --git a/docs/quick_tutorial/retail_forms/tutorial/__init__.py b/docs/quick_tutorial/retail_forms/tutorial/__init__.py
new file mode 100644
index 000000000..dff7457cf
--- /dev/null
+++ b/docs/quick_tutorial/retail_forms/tutorial/__init__.py
@@ -0,0 +1,13 @@
+from pyramid.config import Configurator
+
+
+def main(global_config, **settings):
+ config = Configurator(settings=settings)
+ config.include('pyramid_chameleon')
+ config.add_route('wiki_view', '/')
+ config.add_route('wikipage_add', '/add')
+ config.add_route('wikipage_view', '/{uid}')
+ config.add_route('wikipage_edit', '/{uid}/edit')
+ config.add_static_view('deform_static', 'deform:static/')
+ config.scan('.views')
+ return config.make_wsgi_app()
diff --git a/docs/quick_tutorial/retail_forms/tutorial/tests.py b/docs/quick_tutorial/retail_forms/tutorial/tests.py
new file mode 100644
index 000000000..5a2c40904
--- /dev/null
+++ b/docs/quick_tutorial/retail_forms/tutorial/tests.py
@@ -0,0 +1,36 @@
+import unittest
+
+from pyramid import testing
+
+
+class TutorialViewTests(unittest.TestCase):
+ def setUp(self):
+ self.config = testing.setUp()
+
+ def tearDown(self):
+ testing.tearDown()
+
+ def test_home(self):
+ from .views import WikiViews
+
+ request = testing.DummyRequest()
+ inst = WikiViews(request)
+ response = inst.wiki_view()
+ self.assertEqual(len(response['pages']), 3)
+
+
+class TutorialFunctionalTests(unittest.TestCase):
+ def setUp(self):
+ from tutorial import main
+
+ app = main({})
+ from webtest import TestApp
+
+ self.testapp = TestApp(app)
+
+ def tearDown(self):
+ testing.tearDown()
+
+ def test_home(self):
+ res = self.testapp.get('/', status=200)
+ self.assertIn(b'<title>Wiki: View</title>', res.body)
diff --git a/docs/quick_tutorial/retail_forms/tutorial/views.py b/docs/quick_tutorial/retail_forms/tutorial/views.py
new file mode 100644
index 000000000..2737ebdc4
--- /dev/null
+++ b/docs/quick_tutorial/retail_forms/tutorial/views.py
@@ -0,0 +1,96 @@
+import colander
+import deform.widget
+
+from pyramid.httpexceptions import HTTPFound
+from pyramid.view import view_config
+
+pages = {
+ '100': dict(uid='100', title='Page 100', body='<em>100</em>'),
+ '101': dict(uid='101', title='Page 101', body='<em>101</em>'),
+ '102': dict(uid='102', title='Page 102', body='<em>102</em>')
+}
+
+class WikiPage(colander.MappingSchema):
+ title = colander.SchemaNode(colander.String())
+ body = colander.SchemaNode(
+ colander.String(),
+ widget=deform.widget.RichTextWidget()
+ )
+
+
+class WikiViews(object):
+ def __init__(self, request):
+ self.request = request
+
+ @property
+ def wiki_form(self):
+ schema = WikiPage()
+ return deform.Form(schema, buttons=('submit',))
+
+ @property
+ def reqts(self):
+ return self.wiki_form.get_widget_resources()
+
+ @view_config(route_name='wiki_view', renderer='wiki_view.pt')
+ def wiki_view(self):
+ return dict(pages=pages.values())
+
+ @view_config(route_name='wikipage_add',
+ renderer='wikipage_addedit.pt')
+ def wikipage_add(self):
+ form = self.wiki_form
+
+ if 'submit' in self.request.params:
+ controls = self.request.POST.items()
+ try:
+ appstruct = self.wiki_form.validate(controls)
+ except deform.ValidationFailure as e:
+ # Form is NOT valid
+ return dict(form=e.render())
+
+ # Form is valid, make a new identifier and add to list
+ last_uid = int(sorted(pages.keys())[-1])
+ new_uid = str(last_uid + 1)
+ pages[new_uid] = dict(
+ uid=new_uid, title=appstruct['title'],
+ body=appstruct['body']
+ )
+
+ # Now visit new page
+ url = self.request.route_url('wikipage_view', uid=new_uid)
+ return HTTPFound(url)
+
+ return dict(form=form)
+
+ @view_config(route_name='wikipage_view', renderer='wikipage_view.pt')
+ def wikipage_view(self):
+ uid = self.request.matchdict['uid']
+ page = pages[uid]
+ return dict(page=page)
+
+ @view_config(route_name='wikipage_edit',
+ renderer='wikipage_addedit.pt')
+ def wikipage_edit(self):
+ uid = self.request.matchdict['uid']
+ page = pages[uid]
+
+ wiki_form = self.wiki_form
+
+ if 'submit' in self.request.params:
+ controls = self.request.POST.items()
+ try:
+ appstruct = wiki_form.validate(controls)
+ except deform.ValidationFailure as e:
+ return dict(page=page, form=e.render())
+
+ # Change the content and redirect to the view
+ page['title'] = appstruct['title']
+ page['body'] = appstruct['body']
+
+ url = self.request.route_url('wikipage_view',
+ uid=page['uid'])
+ return HTTPFound(url)
+
+ form = wiki_form.render(page)
+
+ return dict(page=page, form=form) \ No newline at end of file
diff --git a/docs/quick_tutorial/retail_forms/tutorial/wiki_view.pt b/docs/quick_tutorial/retail_forms/tutorial/wiki_view.pt
new file mode 100644
index 000000000..9e3afe495
--- /dev/null
+++ b/docs/quick_tutorial/retail_forms/tutorial/wiki_view.pt
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <title>Wiki: View</title>
+</head>
+<body>
+<h1>Wiki</h1>
+
+<a href="${request.route_url('wikipage_add')}">Add
+ WikiPage</a>
+<ul>
+ <li tal:repeat="page pages">
+ <a href="${request.route_url('wikipage_view', uid=page.uid)}">
+ ${page.title}
+ </a>
+ </li>
+</ul>
+</body>
+</html> \ No newline at end of file
diff --git a/docs/quick_tutorial/retail_forms/tutorial/wikipage_addedit.pt b/docs/quick_tutorial/retail_forms/tutorial/wikipage_addedit.pt
new file mode 100644
index 000000000..586f4c44b
--- /dev/null
+++ b/docs/quick_tutorial/retail_forms/tutorial/wikipage_addedit.pt
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <title>WikiPage: Add/Edit</title>
+ <tal:block tal:repeat="reqt view.reqts['css']">
+ <link rel="stylesheet" type="text/css"
+ href="${request.static_url('deform:static/' + reqt)}"/>
+ </tal:block>
+ <tal:block tal:repeat="reqt view.reqts['js']">
+ <script src="${request.static_url('deform:static/' + reqt)}"
+ type="text/javascript"></script>
+ </tal:block>
+</head>
+<body>
+<h1>Wiki</h1>
+
+<div class="row"
+ tal:repeat="field form">
+ <div class="span2">
+ ${structure:field.title}
+ <span class="req" tal:condition="field.required">*</span>
+ </div>
+ <div class="span2">
+ ${structure:field.serialize()}
+ </div>
+ <ul tal:condition="field.error">
+ <li tal:repeat="error field.error.messages()">
+ ${structure:error}
+ </li>
+ </ul>
+</div>
+
+<script type="text/javascript">
+ deform.load()
+</script>
+</body>
+</html>
diff --git a/docs/quick_tutorial/retail_forms/tutorial/wikipage_view.pt b/docs/quick_tutorial/retail_forms/tutorial/wikipage_view.pt
new file mode 100644
index 000000000..cb9ff526e
--- /dev/null
+++ b/docs/quick_tutorial/retail_forms/tutorial/wikipage_view.pt
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <title>WikiPage: View</title>
+</head>
+<body>
+<a href="${request.route_url('wiki_view')}">
+ Up
+</a> |
+<a href="${request.route_url('wikipage_edit', uid=page.uid)}">
+ Edit
+</a>
+
+<h1>${page.title}</h1>
+<p>${structure: page.body}</p>
+</body>
+</html> \ No newline at end of file
diff --git a/docs/quick_tutorial/sessions.rst b/docs/quick_tutorial/sessions.rst
index ba26d0133..0f284e9a7 100644
--- a/docs/quick_tutorial/sessions.rst
+++ b/docs/quick_tutorial/sessions.rst
@@ -13,8 +13,8 @@ When people use your web application, they frequently perform a task
that requires semi-permanent data to be saved. For example, a shopping
cart. This is called a :term:`session`.
-Pyramid has basic built-in support for sessions, with add-ons such as
-*dogpile.cache* (or your own custom sessioning engine) that provide
+Pyramid has basic built-in support for sessions, with add-ons
+or your own custom sessioning engine) that can provide
richer session support. Let's take a look at the
:ref:`built-in sessioning support <sessions_chapter>`.
diff --git a/docs/quick_tutorial/unit_testing.rst b/docs/quick_tutorial/unit_testing.rst
index 73b33c588..ed33f62d7 100644
--- a/docs/quick_tutorial/unit_testing.rst
+++ b/docs/quick_tutorial/unit_testing.rst
@@ -77,7 +77,7 @@ some ``pyramid.testing`` helpers which we use in the test setup and
teardown. Our one test imports the view, makes a dummy request, and sees
if the view returns what we expected.
-The ``tests.HelloWorldViewTests.test_hello_world`` test is a small
+The ``tests.TutorialViewTests.test_hello_world`` test is a small
example of a unit test. First, we import the view inside each test. Why
not import at the top, like in normal Python code? Because imports can
cause effects that break a test. We'd like our tests to be in *units*,
diff --git a/docs/quick_tutorial/views.rst b/docs/quick_tutorial/views.rst
index 15785e902..529bba0a4 100644
--- a/docs/quick_tutorial/views.rst
+++ b/docs/quick_tutorial/views.rst
@@ -42,7 +42,7 @@ Steps
.. code-block:: bash
- $ cd ..; cp -r function_testing views; cd views
+ $ cd ..; cp -r functional_testing views; cd views
$ $VENV/bin/python setup.py develop
#. Our ``views/tutorial/__init__.py`` gets a lot shorter:
diff --git a/docs/tutorials/wiki/src/tests/tutorial/tests.py b/docs/tutorials/wiki/src/tests/tutorial/tests.py
index c435a4519..5add04c20 100644
--- a/docs/tutorials/wiki/src/tests/tutorial/tests.py
+++ b/docs/tutorials/wiki/src/tests/tutorial/tests.py
@@ -158,11 +158,11 @@ class FunctionalTests(unittest.TestCase):
def test_FrontPage(self):
res = self.testapp.get('/FrontPage', status=200)
- self.assertTrue('FrontPage' in res.body)
+ self.assertTrue(b'FrontPage' in res.body)
def test_unexisting_page(self):
res = self.testapp.get('/SomePage', status=404)
- self.assertTrue('Not Found' in res.body)
+ self.assertTrue(b'Not Found' in res.body)
def test_successful_log_in(self):
res = self.testapp.get( self.viewer_login, status=302)
@@ -170,48 +170,48 @@ class FunctionalTests(unittest.TestCase):
def test_failed_log_in(self):
res = self.testapp.get( self.viewer_wrong_login, status=200)
- self.assertTrue('login' in res.body)
+ self.assertTrue(b'login' in res.body)
def test_logout_link_present_when_logged_in(self):
res = self.testapp.get( self.viewer_login, status=302)
res = self.testapp.get('/FrontPage', status=200)
- self.assertTrue('Logout' in res.body)
+ self.assertTrue(b'Logout' in res.body)
def test_logout_link_not_present_after_logged_out(self):
res = self.testapp.get( self.viewer_login, status=302)
res = self.testapp.get('/FrontPage', status=200)
res = self.testapp.get('/logout', status=302)
- self.assertTrue('Logout' not in res.body)
+ self.assertTrue(b'Logout' not in res.body)
def test_anonymous_user_cannot_edit(self):
res = self.testapp.get('/FrontPage/edit_page', status=200)
- self.assertTrue('Login' in res.body)
+ self.assertTrue(b'Login' in res.body)
def test_anonymous_user_cannot_add(self):
res = self.testapp.get('/add_page/NewPage', status=200)
- self.assertTrue('Login' in res.body)
+ self.assertTrue(b'Login' in res.body)
def test_viewer_user_cannot_edit(self):
res = self.testapp.get( self.viewer_login, status=302)
res = self.testapp.get('/FrontPage/edit_page', status=200)
- self.assertTrue('Login' in res.body)
+ self.assertTrue(b'Login' in res.body)
def test_viewer_user_cannot_add(self):
res = self.testapp.get( self.viewer_login, status=302)
res = self.testapp.get('/add_page/NewPage', status=200)
- self.assertTrue('Login' in res.body)
+ self.assertTrue(b'Login' in res.body)
def test_editors_member_user_can_edit(self):
res = self.testapp.get( self.editor_login, status=302)
res = self.testapp.get('/FrontPage/edit_page', status=200)
- self.assertTrue('Editing' in res.body)
+ self.assertTrue(b'Editing' in res.body)
def test_editors_member_user_can_add(self):
res = self.testapp.get( self.editor_login, status=302)
res = self.testapp.get('/add_page/NewPage', status=200)
- self.assertTrue('Editing' in res.body)
+ self.assertTrue(b'Editing' in res.body)
def test_editors_member_user_can_view(self):
res = self.testapp.get( self.editor_login, status=302)
res = self.testapp.get('/FrontPage', status=200)
- self.assertTrue('FrontPage' in res.body)
+ self.assertTrue(b'FrontPage' in res.body)
diff --git a/docs/tutorials/wiki2/src/authorization/tutorial/scripts/initializedb.py b/docs/tutorials/wiki2/src/authorization/tutorial/scripts/initializedb.py
index 092e359ce..23a5f13f4 100644
--- a/docs/tutorials/wiki2/src/authorization/tutorial/scripts/initializedb.py
+++ b/docs/tutorials/wiki2/src/authorization/tutorial/scripts/initializedb.py
@@ -33,5 +33,5 @@ def main(argv=sys.argv):
DBSession.configure(bind=engine)
Base.metadata.create_all(engine)
with transaction.manager:
- model = Page('FrontPage', 'This is the front page')
+ model = Page(name='FrontPage', data='This is the front page')
DBSession.add(model)
diff --git a/docs/tutorials/wiki2/src/authorization/tutorial/tests.py b/docs/tutorials/wiki2/src/authorization/tutorial/tests.py
index 5dcee127b..9f01d2da5 100644
--- a/docs/tutorials/wiki2/src/authorization/tutorial/tests.py
+++ b/docs/tutorials/wiki2/src/authorization/tutorial/tests.py
@@ -14,7 +14,7 @@ def _initTestingDB():
Base.metadata.create_all(engine)
DBSession.configure(bind=engine)
with transaction.manager:
- model = Page('FrontPage', 'This is the front page')
+ model = Page(name='FrontPage', data='This is the front page')
DBSession.add(model)
return DBSession
@@ -59,7 +59,7 @@ class ViewPageTests(unittest.TestCase):
from tutorial.models import Page
request = testing.DummyRequest()
request.matchdict['pagename'] = 'IDoExist'
- page = Page('IDoExist', 'Hello CruelWorld IDoExist')
+ page = Page(name='IDoExist', data='Hello CruelWorld IDoExist')
self.session.add(page)
_registerRoutes(self.config)
info = self._callFUT(request)
@@ -126,7 +126,7 @@ class EditPageTests(unittest.TestCase):
_registerRoutes(self.config)
request = testing.DummyRequest()
request.matchdict = {'pagename':'abc'}
- page = Page('abc', 'hello')
+ page = Page(name='abc', data='hello')
self.session.add(page)
info = self._callFUT(request)
self.assertEqual(info['page'], page)
@@ -139,7 +139,7 @@ class EditPageTests(unittest.TestCase):
request = testing.DummyRequest({'form.submitted':True,
'body':'Hello yo!'})
request.matchdict = {'pagename':'abc'}
- page = Page('abc', 'hello')
+ page = Page(name='abc', data='hello')
self.session.add(page)
response = self._callFUT(request)
self.assertEqual(response.location, 'http://example.com/abc')
diff --git a/docs/tutorials/wiki2/src/authorization/tutorial/views.py b/docs/tutorials/wiki2/src/authorization/tutorial/views.py
index 0d085b0e2..b6dbbf5f6 100644
--- a/docs/tutorials/wiki2/src/authorization/tutorial/views.py
+++ b/docs/tutorials/wiki2/src/authorization/tutorial/views.py
@@ -63,12 +63,12 @@ def add_page(request):
pagename = request.matchdict['pagename']
if 'form.submitted' in request.params:
body = request.params['body']
- page = Page(pagename, body)
+ page = Page(name=pagename, data=body)
DBSession.add(page)
return HTTPFound(location = request.route_url('view_page',
pagename=pagename))
save_url = request.route_url('add_page', pagename=pagename)
- page = Page('', '')
+ page = Page(name='', data='')
return dict(page=page, save_url=save_url,
logged_in=authenticated_userid(request))
diff --git a/docs/tutorials/wiki2/src/models/tutorial/scripts/initializedb.py b/docs/tutorials/wiki2/src/models/tutorial/scripts/initializedb.py
index 092e359ce..23a5f13f4 100644
--- a/docs/tutorials/wiki2/src/models/tutorial/scripts/initializedb.py
+++ b/docs/tutorials/wiki2/src/models/tutorial/scripts/initializedb.py
@@ -33,5 +33,5 @@ def main(argv=sys.argv):
DBSession.configure(bind=engine)
Base.metadata.create_all(engine)
with transaction.manager:
- model = Page('FrontPage', 'This is the front page')
+ model = Page(name='FrontPage', data='This is the front page')
DBSession.add(model)
diff --git a/docs/tutorials/wiki2/src/tests/tutorial/scripts/initializedb.py b/docs/tutorials/wiki2/src/tests/tutorial/scripts/initializedb.py
index 092e359ce..23a5f13f4 100644
--- a/docs/tutorials/wiki2/src/tests/tutorial/scripts/initializedb.py
+++ b/docs/tutorials/wiki2/src/tests/tutorial/scripts/initializedb.py
@@ -33,5 +33,5 @@ def main(argv=sys.argv):
DBSession.configure(bind=engine)
Base.metadata.create_all(engine)
with transaction.manager:
- model = Page('FrontPage', 'This is the front page')
+ model = Page(name='FrontPage', data='This is the front page')
DBSession.add(model)
diff --git a/docs/tutorials/wiki2/src/tests/tutorial/tests.py b/docs/tutorials/wiki2/src/tests/tutorial/tests.py
index 3e96d0a82..4ee30685e 100644
--- a/docs/tutorials/wiki2/src/tests/tutorial/tests.py
+++ b/docs/tutorials/wiki2/src/tests/tutorial/tests.py
@@ -15,7 +15,7 @@ def _initTestingDB():
Base.metadata.create_all(engine)
DBSession.configure(bind=engine)
with transaction.manager:
- model = Page('FrontPage', 'This is the front page')
+ model = Page(name='FrontPage', data='This is the front page')
DBSession.add(model)
return DBSession
@@ -82,7 +82,7 @@ class ViewPageTests(unittest.TestCase):
from tutorial.models import Page
request = testing.DummyRequest()
request.matchdict['pagename'] = 'IDoExist'
- page = Page('IDoExist', 'Hello CruelWorld IDoExist')
+ page = Page(name='IDoExist', data='Hello CruelWorld IDoExist')
self.session.add(page)
_registerRoutes(self.config)
info = self._callFUT(request)
@@ -150,7 +150,7 @@ class EditPageTests(unittest.TestCase):
_registerRoutes(self.config)
request = testing.DummyRequest()
request.matchdict = {'pagename':'abc'}
- page = Page('abc', 'hello')
+ page = Page(name='abc', data='hello')
self.session.add(page)
info = self._callFUT(request)
self.assertEqual(info['page'], page)
@@ -163,7 +163,7 @@ class EditPageTests(unittest.TestCase):
request = testing.DummyRequest({'form.submitted':True,
'body':'Hello yo!'})
request.matchdict = {'pagename':'abc'}
- page = Page('abc', 'hello')
+ page = Page(name='abc', data='hello')
self.session.add(page)
response = self._callFUT(request)
self.assertEqual(response.location, 'http://example.com/abc')
diff --git a/docs/tutorials/wiki2/src/tests/tutorial/views.py b/docs/tutorials/wiki2/src/tests/tutorial/views.py
index 0d085b0e2..b6dbbf5f6 100644
--- a/docs/tutorials/wiki2/src/tests/tutorial/views.py
+++ b/docs/tutorials/wiki2/src/tests/tutorial/views.py
@@ -63,12 +63,12 @@ def add_page(request):
pagename = request.matchdict['pagename']
if 'form.submitted' in request.params:
body = request.params['body']
- page = Page(pagename, body)
+ page = Page(name=pagename, data=body)
DBSession.add(page)
return HTTPFound(location = request.route_url('view_page',
pagename=pagename))
save_url = request.route_url('add_page', pagename=pagename)
- page = Page('', '')
+ page = Page(name='', data='')
return dict(page=page, save_url=save_url,
logged_in=authenticated_userid(request))
diff --git a/docs/tutorials/wiki2/src/views/tutorial/scripts/initializedb.py b/docs/tutorials/wiki2/src/views/tutorial/scripts/initializedb.py
index 092e359ce..23a5f13f4 100644
--- a/docs/tutorials/wiki2/src/views/tutorial/scripts/initializedb.py
+++ b/docs/tutorials/wiki2/src/views/tutorial/scripts/initializedb.py
@@ -33,5 +33,5 @@ def main(argv=sys.argv):
DBSession.configure(bind=engine)
Base.metadata.create_all(engine)
with transaction.manager:
- model = Page('FrontPage', 'This is the front page')
+ model = Page(name='FrontPage', data='This is the front page')
DBSession.add(model)
diff --git a/docs/tutorials/wiki2/src/views/tutorial/tests.py b/docs/tutorials/wiki2/src/views/tutorial/tests.py
index 5dcee127b..9f01d2da5 100644
--- a/docs/tutorials/wiki2/src/views/tutorial/tests.py
+++ b/docs/tutorials/wiki2/src/views/tutorial/tests.py
@@ -14,7 +14,7 @@ def _initTestingDB():
Base.metadata.create_all(engine)
DBSession.configure(bind=engine)
with transaction.manager:
- model = Page('FrontPage', 'This is the front page')
+ model = Page(name='FrontPage', data='This is the front page')
DBSession.add(model)
return DBSession
@@ -59,7 +59,7 @@ class ViewPageTests(unittest.TestCase):
from tutorial.models import Page
request = testing.DummyRequest()
request.matchdict['pagename'] = 'IDoExist'
- page = Page('IDoExist', 'Hello CruelWorld IDoExist')
+ page = Page(name='IDoExist', data='Hello CruelWorld IDoExist')
self.session.add(page)
_registerRoutes(self.config)
info = self._callFUT(request)
@@ -126,7 +126,7 @@ class EditPageTests(unittest.TestCase):
_registerRoutes(self.config)
request = testing.DummyRequest()
request.matchdict = {'pagename':'abc'}
- page = Page('abc', 'hello')
+ page = Page(name='abc', data='hello')
self.session.add(page)
info = self._callFUT(request)
self.assertEqual(info['page'], page)
@@ -139,7 +139,7 @@ class EditPageTests(unittest.TestCase):
request = testing.DummyRequest({'form.submitted':True,
'body':'Hello yo!'})
request.matchdict = {'pagename':'abc'}
- page = Page('abc', 'hello')
+ page = Page(name='abc', data='hello')
self.session.add(page)
response = self._callFUT(request)
self.assertEqual(response.location, 'http://example.com/abc')
diff --git a/docs/tutorials/wiki2/src/views/tutorial/views.py b/docs/tutorials/wiki2/src/views/tutorial/views.py
index 5a9c75a61..42ef77b98 100644
--- a/docs/tutorials/wiki2/src/views/tutorial/views.py
+++ b/docs/tutorials/wiki2/src/views/tutorial/views.py
@@ -47,12 +47,12 @@ def add_page(request):
pagename = request.matchdict['pagename']
if 'form.submitted' in request.params:
body = request.params['body']
- page = Page(pagename, body)
+ page = Page(name=pagename, data=body)
DBSession.add(page)
return HTTPFound(location = request.route_url('view_page',
pagename=pagename))
save_url = request.route_url('add_page', pagename=pagename)
- page = Page('', '')
+ page = Page(name='', data='')
return dict(page=page, save_url=save_url)
@view_config(route_name='edit_page', renderer='templates/edit.pt')