summaryrefslogtreecommitdiff
path: root/docs/tutorials/wiki2/definingviews.rst
diff options
context:
space:
mode:
authorMichael Merickel <michael@merickel.org>2015-10-21 16:57:52 -0500
committerMichael Merickel <michael@merickel.org>2015-10-21 16:57:52 -0500
commitadb9377a963d7fdc7b7bf616740fb5dd2e40b2bf (patch)
tree1038d03a21148607c79f740f0b32b147929251bf /docs/tutorials/wiki2/definingviews.rst
parent452fdbef94bb29560497ec8a9ccbc3b9c2ecd2dd (diff)
parentd4221720b8409eafb65b301562be327af0196c7e (diff)
downloadpyramid-adb9377a963d7fdc7b7bf616740fb5dd2e40b2bf.tar.gz
pyramid-adb9377a963d7fdc7b7bf616740fb5dd2e40b2bf.tar.bz2
pyramid-adb9377a963d7fdc7b7bf616740fb5dd2e40b2bf.zip
Merge branch 'master' into feature/alchemy-scaffold-update
Diffstat (limited to 'docs/tutorials/wiki2/definingviews.rst')
-rw-r--r--docs/tutorials/wiki2/definingviews.rst227
1 files changed, 115 insertions, 112 deletions
diff --git a/docs/tutorials/wiki2/definingviews.rst b/docs/tutorials/wiki2/definingviews.rst
index 49dbed50f..0b495445a 100644
--- a/docs/tutorials/wiki2/definingviews.rst
+++ b/docs/tutorials/wiki2/definingviews.rst
@@ -11,8 +11,8 @@ The request object has a dictionary as an attribute named ``matchdict``. A
substrings of the path in the :term:`request` URL. For instance, if a call to
:meth:`pyramid.config.Configurator.add_route` has the pattern ``/{one}/{two}``,
and a user visits ``http://example.com/foo/bar``, our pattern would be matched
-against ``/foo/bar`` and the ``matchdict`` would look like: ``{'one':'foo',
-'two':'bar'}``
+against ``/foo/bar`` and the ``matchdict`` would look like ``{'one':'foo',
+'two':'bar'}``.
Declaring Dependencies in Our ``setup.py`` File
===============================================
@@ -23,26 +23,27 @@ application was generated by the ``pcreate`` command; it doesn't know
about our custom application requirements.
We need to add a dependency on the ``docutils`` package to our ``tutorial``
-package's ``setup.py`` file by assigning this dependency to the ``requires`` parameter in ``setup()``.
+package's ``setup.py`` file by assigning this dependency to the ``requires``
+parameter in the ``setup()`` function.
Open ``tutorial/setup.py`` and edit it to look like the following:
.. literalinclude:: src/views/setup.py
:linenos:
- :language: python
:emphasize-lines: 20
+ :language: python
-(Only the highlighted line needs to be added.)
+Only the highlighted line needs to be added.
Running ``setup.py develop``
============================
-Since a new software dependency was added, you will need to rerun ``python
-setup.py develop`` inside the root of the ``tutorial`` package to obtain and
-register the newly added dependency distribution.
+Since a new software dependency was added, you will need to run ``python
+setup.py develop`` again inside the root of the ``tutorial`` package to obtain
+and register the newly added dependency distribution.
Make sure your current working directory is the root of the project (the
-directory in which setup.py lives) and execute the following command.
+directory in which ``setup.py`` lives) and execute the following command.
On UNIX:
@@ -63,21 +64,24 @@ like::
Finished processing dependencies for tutorial==0.0
-Changing the ``views.py`` File
-==============================
+Adding view functions in ``views.py``
+=====================================
-It's time for a major change. Open ``tutorial/tutorial/views.py`` and edit it to look like the following:
+It's time for a major change. Open ``tutorial/tutorial/views.py`` and edit it
+to look like the following:
.. literalinclude:: src/views/tutorial/views.py
:linenos:
:language: python
- :emphasize-lines: 1-7,12,15-70
+ :emphasize-lines: 1-7,14,16-72
-(The highlighted lines are the ones that need to be added or edited.)
+The highlighted lines need to be added or edited.
-We got rid of the ``my_view`` view function and its decorator that was
-added when we originally rendered the ``alchemy`` scaffold. It was only an
-example and isn't relevant to our application.
+We added some imports and created a regular expression to find "WikiWords".
+
+We got rid of the ``my_view`` view function and its decorator that was added
+when we originally rendered the ``alchemy`` scaffold. It was only an example
+and isn't relevant to our application.
Then we added four :term:`view callable` functions to our ``views.py``
module:
@@ -87,13 +91,12 @@ module:
* ``add_page()`` - Allows the user to add a page.
* ``edit_page()`` - Allows the user to edit a page.
-We'll describe each one briefly and show the resulting ``views.py`` file
-afterward.
+We'll describe each one briefly in the following sections.
.. note::
There is nothing special about the filename ``views.py``. A project may
- have many view callables throughout its codebase in arbitrarily-named
+ have many view callables throughout its codebase in arbitrarily named
files. Files implementing view callables often have ``view`` in their
filenames (or may live in a Python subpackage of your application package
named ``views``), but this is only by convention.
@@ -101,39 +104,44 @@ afterward.
The ``view_wiki`` view function
-------------------------------
-``view_wiki()`` is the :term:`default view` that gets called when a request
-is made to the root URL of our wiki. It always redirects to
-a URL which represents the path to our "FrontPage".
+Following is the code for the ``view_wiki`` view function and its decorator:
.. literalinclude:: src/views/tutorial/views.py
- :lines: 18-21
+ :lines: 20-24
+ :lineno-start: 20
:linenos:
:language: python
-``view_wiki()`` returns an instance of the
-:class:`pyramid.httpexceptions.HTTPFound` class (instances of which implement
-the :class:`pyramid.interfaces.IResponse` interface like
-:class:`pyramid.response.Response` does).
+``view_wiki()`` is the :term:`default view` that gets called when a request is
+made to the root URL of our wiki. It always redirects to an URL which
+represents the path to our "FrontPage".
-It uses the :meth:`pyramid.request.Request.route_url` API to construct a
-URL to the ``FrontPage`` page (e.g. ``http://localhost:6543/FrontPage``), which
-is used as the "location" of the ``HTTPFound`` response, forming an HTTP redirect.
+The ``view_wiki`` view callable always redirects to the URL of a Page resource
+named "FrontPage". To do so, it returns an instance of the
+:class:`pyramid.httpexceptions.HTTPFound` class (instances of which implement
+the :class:`pyramid.interfaces.IResponse` interface, like
+:class:`pyramid.response.Response` does). It uses the
+:meth:`pyramid.request.Request.route_url` API to construct an URL to the
+``FrontPage`` page (i.e., ``http://localhost:6543/FrontPage``), and uses it as
+the "location" of the ``HTTPFound`` response, forming an HTTP redirect.
The ``view_page`` view function
-------------------------------
-``view_page()`` is used to display a single page of our
-wiki. It renders the :term:`reStructuredText` body of a page (stored as
-the ``data`` attribute of a ``Page`` model object) as HTML. Then it substitutes an
-HTML anchor for each *WikiWord* reference in the rendered HTML using a
-compiled regular expression.
+Here is the code for the ``view_page`` view function and its decorator:
.. literalinclude:: src/views/tutorial/views.py
- :lines: 23-43
+ :lines: 25-45
+ :lineno-start: 25
:linenos:
:language: python
-The ``check()`` function is used as the first argument to
+``view_page()`` is used to display a single page of our wiki. It renders the
+:term:`reStructuredText` body of a page (stored as the ``data`` attribute of a
+``Page`` model object) as HTML. Then it substitutes an HTML anchor for each
+*WikiWord* reference in the rendered HTML using a compiled regular expression.
+
+The curried function named ``check`` is used as the first argument to
``wikiwords.sub``, indicating that it should be called to provide a value for
each WikiWord match found in the content. If the wiki already contains a
page with the matched WikiWord name, ``check()`` generates a view
@@ -156,6 +164,14 @@ renderer used will be the ``templates/view.pt`` template, as indicated in the
The ``add_page`` view function
------------------------------
+Here is the code for the ``add_page`` view function and its decorator:
+
+.. literalinclude:: src/views/tutorial/views.py
+ :lines: 47-58
+ :lineno-start: 47
+ :linenos:
+ :language: python
+
``add_page()`` is invoked when a user clicks on a *WikiWord* which
isn't yet represented as a page in the system. The ``check`` function
within the ``view_page`` view generates URLs to this view.
@@ -164,26 +180,21 @@ when we want to add a page object. The ``matchdict`` attribute of the
request passed to the ``add_page()`` view will have the values we need
to construct URLs and find model objects.
-.. literalinclude:: src/views/tutorial/views.py
- :lines: 45-56
- :linenos:
- :language: python
-
The ``matchdict`` will have a ``'pagename'`` key that matches the name of
the page we'd like to add. If our add view is invoked via,
-e.g. ``http://localhost:6543/add_page/SomeName``, the value for
+e.g., ``http://localhost:6543/add_page/SomeName``, the value for
``'pagename'`` in the ``matchdict`` will be ``'SomeName'``.
-If the view execution *is* a result of a form submission (i.e. the expression
-``'form.submitted' in request.params`` is ``True``), we scrape the page body
+If the view execution *is* a result of a form submission (i.e., the expression
+``'form.submitted' in request.params`` is ``True``), we grab the page body
from the form data, create a Page object with this page body and the name
taken from ``matchdict['pagename']``, and save it into the database using
``DBSession.add``. We then redirect back to the ``view_page`` view for the
newly created page.
-If the view execution is *not* a result of a form submission (i.e. the
+If the view execution is *not* a result of a form submission (i.e., the
expression ``'form.submitted' in request.params`` is ``False``), the view
-callable renders a template. To do so, it generates a "save url" which the
+callable renders a template. To do so, it generates a ``save_url`` which the
template uses as the form post URL during rendering. We're lazy here, so
we're going to use the same template (``templates/edit.pt``) for the add
view as well as the page edit view. To do so we create a dummy Page object
@@ -194,38 +205,41 @@ with this view to a response.
The ``edit_page`` view function
-------------------------------
+Here is the code for the ``edit_page`` view function and its decorator:
+
+.. literalinclude:: src/views/tutorial/views.py
+ :lines: 60-72
+ :lineno-start: 60
+ :linenos:
+ :language: python
+
``edit_page()`` is invoked when a user clicks the "Edit this
Page" button on the view form. It renders an edit form but it also acts as
the handler for the form it renders. The ``matchdict`` attribute of the
request passed to the ``edit_page`` view will have a ``'pagename'`` key
matching the name of the page the user wants to edit.
-.. literalinclude:: src/views/tutorial/views.py
- :lines: 58-70
- :linenos:
- :language: python
-
-If the view execution *is* a result of a form submission (i.e. the expression
+If the view execution *is* a result of a form submission (i.e., the expression
``'form.submitted' in request.params`` is ``True``), the view grabs the
``body`` element of the request parameters and sets it as the ``data``
attribute of the page object. It then redirects to the ``view_page`` view
of the wiki page.
-If the view execution is *not* a result of a form submission (i.e. the
+If the view execution is *not* a result of a form submission (i.e., the
expression ``'form.submitted' in request.params`` is ``False``), the view
simply renders the edit form, passing the page object and a ``save_url``
which will be used as the action of the generated form.
-Adding Templates
+Adding templates
================
The ``view_page``, ``add_page`` and ``edit_page`` views that we've added
-reference a :term:`template`. Each template is a :term:`Chameleon` :term:`ZPT`
-template. These templates will live in the ``templates`` directory of our
-tutorial package. Chameleon templates must have a ``.pt`` extension to be
-recognized as such.
+reference a :term:`template`. Each template is a :term:`Chameleon`
+:term:`ZPT` template. These templates will live in the ``templates``
+directory of our tutorial package. Chameleon templates must have a ``.pt``
+extension to be recognized as such.
-The ``view.pt`` Template
+The ``view.pt`` template
------------------------
Create ``tutorial/tutorial/templates/view.pt`` and add the following
@@ -233,20 +247,18 @@ content:
.. literalinclude:: src/views/tutorial/templates/view.pt
:linenos:
- :language: xml
+ :language: html
This template is used by ``view_page()`` for displaying a single
wiki page. It includes:
-- A ``div`` element that is replaced with the ``content``
- value provided by the view (rows 45-47). ``content``
- contains HTML, so the ``structure`` keyword is used
- to prevent escaping it (i.e. changing ">" to "&gt;", etc.)
-- A link that points
- at the "edit" URL which invokes the ``edit_page`` view for
- the page being viewed (rows 49-51).
+- A ``div`` element that is replaced with the ``content`` value provided by
+ the view (lines 36-38). ``content`` contains HTML, so the ``structure``
+ keyword is used to prevent escaping it (i.e., changing ">" to "&gt;", etc.)
+- A link that points at the "edit" URL which invokes the ``edit_page`` view
+ for the page being viewed (lines 40-42).
-The ``edit.pt`` Template
+The ``edit.pt`` template
------------------------
Create ``tutorial/tutorial/templates/edit.pt`` and add the following
@@ -254,44 +266,38 @@ content:
.. literalinclude:: src/views/tutorial/templates/edit.pt
:linenos:
- :language: xml
+ :language: html
-This template is used by ``add_page()`` and ``edit_page()`` for adding
-and editing a wiki page. It displays
-a page containing a form that includes:
+This template is used by ``add_page()`` and ``edit_page()`` for adding and
+editing a wiki page. It displays a page containing a form that includes:
- A 10 row by 60 column ``textarea`` field named ``body`` that is filled
- with any existing page data when it is rendered (rows 46-47).
-- A submit button that has the name ``form.submitted`` (row 48).
+ with any existing page data when it is rendered (line 45).
+- A submit button that has the name ``form.submitted`` (line 48).
-The form POSTs back to the "save_url" argument supplied
-by the view (row 45). The view will use the ``body`` and
-``form.submitted`` values.
+The form POSTs back to the ``save_url`` argument supplied by the view (line
+43). The view will use the ``body`` and ``form.submitted`` values.
-.. note:: Our templates use a ``request`` object that
- none of our tutorial views return in their dictionary.
- ``request`` is one of several
- names that are available "by default" in a template when a template
- renderer is used. See :ref:`renderer_system_values` for
- information about other names that are available by default
- when a template is used as a renderer.
+.. note:: Our templates use a ``request`` object that none of our tutorial
+ views return in their dictionary. ``request`` is one of several names that
+ are available "by default" in a template when a template renderer is used.
+ See :ref:`renderer_system_values` for information about other names that
+ are available by default when a template is used as a renderer.
Static Assets
-------------
-Our templates name a single static asset named ``pylons.css``. We don't need
-to create this file within our package's ``static`` directory because it was
-provided at the time we created the project. This file is a little too long
-to replicate within the body of this guide, however it is available `online
-<https://github.com/Pylons/pyramid/blob/master/docs/tutorials/wiki2/src/views/tutorial/static/pylons.css>`_.
+Our templates name static assets, including CSS and images. We don't need
+to create these files within our package's ``static`` directory because they
+were provided at the time we created the project.
-This CSS file will be accessed via
-e.g. ``http://localhost:6543/static/pylons.css`` by virtue of the call to
+As an example, the CSS file will be accessed via
+``http://localhost:6543/static/theme.css`` by virtue of the call to the
``add_static_view`` directive we've made in the ``__init__.py`` file. Any
number and type of static assets can be placed in this directory (or
subdirectories) and are just referred to by URL or by using the convenience
-method ``static_url``
-e.g. ``request.static_url('{{package}}:static/foo.css')`` within templates.
+method ``static_url``, e.g.,
+``request.static_url('<package>:static/foo.css')`` within templates.
Adding Routes to ``__init__.py``
================================
@@ -334,33 +340,30 @@ something like:
.. literalinclude:: src/views/tutorial/__init__.py
:linenos:
- :language: python
:emphasize-lines: 19-22
+ :language: python
-(The highlighted lines are the ones that need to be added or edited.)
+The highlighted lines are the ones that need to be added or edited.
-Viewing the Application in a Browser
+Viewing the application in a browser
====================================
We can finally examine our application in a browser (See
:ref:`wiki2-start-the-application`). Launch a browser and visit
-each of the following URLs, check that the result is as expected:
+each of the following URLs, checking that the result is as expected:
-- http://localhost:6543 in a browser invokes the
- ``view_wiki`` view. This always redirects to the ``view_page`` view
- of the FrontPage page object.
+- http://localhost:6543/ invokes the ``view_wiki`` view. This always
+ redirects to the ``view_page`` view of the ``FrontPage`` page object.
-- http://localhost:6543/FrontPage in a browser invokes
- the ``view_page`` view of the front page object.
+- http://localhost:6543/FrontPage invokes the ``view_page`` view of the front
+ page object.
-- http://localhost:6543/FrontPage/edit_page in a browser
- invokes the edit view for the front page object.
+- http://localhost:6543/FrontPage/edit_page invokes the edit view for the
+ front page object.
-- http://localhost:6543/add_page/SomePageName in a
- browser invokes the add view for a page.
+- http://localhost:6543/add_page/SomePageName invokes the add view for a page.
- To generate an error, visit http://localhost:6543/foobars/edit_page which
- will generate a ``NoResultFound: No row was found for one()`` error.
- You'll see an interactive traceback facility provided
- by :term:`pyramid_debugtoolbar`.
-
+ will generate a ``NoResultFound: No row was found for one()`` error. You'll
+ see an interactive traceback facility provided by
+ :term:`pyramid_debugtoolbar`.