summaryrefslogtreecommitdiff
path: root/docs/tutorials
diff options
context:
space:
mode:
authorChris McDonough <chrism@plope.com>2011-03-20 18:08:58 -0400
committerChris McDonough <chrism@plope.com>2011-03-20 18:08:58 -0400
commit6ed41a034df40dcc6632432544742ebefe3162ba (patch)
tree0ba9ce995207e9acf2131a9c84da7e792797cb0c /docs/tutorials
parent21d08467e87a5262d97cc64814061d87ed12fbb1 (diff)
downloadpyramid-6ed41a034df40dcc6632432544742ebefe3162ba.tar.gz
pyramid-6ed41a034df40dcc6632432544742ebefe3162ba.tar.bz2
pyramid-6ed41a034df40dcc6632432544742ebefe3162ba.zip
review changes to sqla tutorial
Diffstat (limited to 'docs/tutorials')
-rw-r--r--docs/tutorials/wiki2/authorization.rst77
-rw-r--r--docs/tutorials/wiki2/basiclayout.rst57
-rw-r--r--docs/tutorials/wiki2/definingmodels.rst40
-rw-r--r--docs/tutorials/wiki2/definingviews.rst223
4 files changed, 191 insertions, 206 deletions
diff --git a/docs/tutorials/wiki2/authorization.rst b/docs/tutorials/wiki2/authorization.rst
index 0f3a9c31c..64cab30db 100644
--- a/docs/tutorials/wiki2/authorization.rst
+++ b/docs/tutorials/wiki2/authorization.rst
@@ -27,13 +27,13 @@ Adding A Root Factory
~~~~~~~~~~~~~~~~~~~~~
We're going to start to use a custom :term:`root factory` within our
-``__init__.py`` file. The objects generated by the root factory will be
-used as the :term:`context` of each request to our application. In
-order for :app:`Pyramid` declarative security to work properly, the
-context object generated during a request must be decorated with
-security declarations; when we begin to use a custom root factory to
-generate our contexts, we can begin to make use of the declarative
-security features of :app:`Pyramid`.
+``__init__.py`` file. The objects generated by the root factory will be used
+as the :term:`context` of each request to our application. We do this to
+allow :app:`Pyramid` declarative security to work properly. The context
+object generated by the root factory during a request will be decorated with
+security declarations. When we begin to use a custom root factory to generate
+our contexts, we can begin to make use of the declarative security features
+of :app:`Pyramid`.
We'll modify our ``__init__.py``, passing in a :term:`root factory` to our
:term:`Configurator` constructor. We'll point it at a new class we create
@@ -45,19 +45,17 @@ inside our ``models.py`` file. Add the following statements to your
:linenos:
:language: python
-The ``RootFactory`` class we've just added will be used by
-:app:`Pyramid` to construct a ``context`` object. The context is
-attached to the request object passed to our view callables as the
-``context`` attribute.
+The ``RootFactory`` class we've just added will be used by :app:`Pyramid` to
+construct a ``context`` object. The context is attached to the request
+object passed to our view callables as the ``context`` attribute.
-All of our context objects will possess an ``__acl__`` attribute that
-allows :data:`pyramid.security.Everyone` (a special principal) to
-view all pages, while allowing only a :term:`principal` named
-``group:editors`` to edit and add pages. The ``__acl__`` attribute
-attached to a context is interpreted specially by :app:`Pyramid` as
-an access control list during view callable execution. See
-:ref:`assigning_acls` for more information about what an :term:`ACL`
-represents.
+The context object generated by our root factory will possess an ``__acl__``
+attribute that allows :data:`pyramid.security.Everyone` (a special principal)
+to view all pages, while allowing only a :term:`principal` named
+``group:editors`` to edit and add pages. The ``__acl__`` attribute attached
+to a context is interpreted specially by :app:`Pyramid` as an access control
+list during view callable execution. See :ref:`assigning_acls` for more
+information about what an :term:`ACL` represents.
.. note: Although we don't use the functionality here, the ``factory`` used
to create route contexts may differ per-route as opposed to globally. See
@@ -94,35 +92,36 @@ representing a :term:`dotted Python name`, which points at the
``groupfinder`` function in the current directory's ``security.py`` file. We
haven't added that module yet, but we're about to.
-We'll also change ``__init__.py`` to add a
-:meth:`pyramid.config.Configurator.add_view` call that points at our
-``login`` :term:`view callable`, also known as a :term:`forbidden view`:
+We'll also change ``__init__.py``, adding a call to
+:meth:`pyramid.config.Configurator.add_view` that points at our ``login``
+:term:`view callable`. This is also known as a :term:`forbidden view`:
.. literalinclude:: src/authorization/tutorial/__init__.py
:lines: 24-26
:linenos:
:language: python
-This configures our newly created login view to show up when :app:`Pyramid`
-detects that a view invocation can not be authorized.
+A forbidden view configures our newly created login view to show up when
+:app:`Pyramid` detects that a view invocation can not be authorized.
-Also, we'll add
-``view_permission`` arguments with the value ``edit`` to the ``edit_page``
-and ``add_page`` routes. This indicates that the view callables which these
-routes reference cannot be invoked without the authenticated user possessing
-the ``edit`` permission with respect to the current context.
+We'll also add ``view_permission`` arguments with the value ``edit`` to the
+``edit_page`` and ``add_page`` routes. This indicates that the view
+callables which these routes reference cannot be invoked without the
+authenticated user possessing the ``edit`` permission with respect to the
+current context.
.. literalinclude:: src/authorization/tutorial/__init__.py
:lines: 32-39
:linenos:
:language: python
-This makes the assertion that only users who possess the effective ``edit``
-permission at the time of the request may invoke those two views. We've
-granted the ``group:editors`` principal the ``edit`` permission at the root
-model via its ACL, so only the a user whom is a member of the group named
-``group:editors`` will able to invoke the views associated with the
-``add_page`` or ``edit_page`` routes.
+Adding these ``view_permission`` arguments causes Pyramid to make the
+assertion that only users who possess the effective ``edit`` permission at
+the time of the request may invoke those two views. We've granted the
+``group:editors`` principal the ``edit`` permission at the root model via its
+ACL, so only the a user whom is a member of the group named ``group:editors``
+will able to invoke the views associated with the ``add_page`` or
+``edit_page`` routes.
Viewing Your Changes
~~~~~~~~~~~~~~~~~~~~
@@ -186,8 +185,8 @@ Changing Existing Views
~~~~~~~~~~~~~~~~~~~~~~~
Then we need to change each of our ``view_page``, ``edit_page`` and
-``add_page`` views in ``views.py`` to pass a "logged in" parameter to
-its template. We'll add something like this to each view body:
+``add_page`` views in ``views.py`` to pass a "logged in" parameter to its
+template. We'll add something like this to each view body:
.. ignore-next-block
.. code-block:: python
@@ -196,8 +195,8 @@ its template. We'll add something like this to each view body:
from pyramid.security import authenticated_userid
logged_in = authenticated_userid(request)
-We'll then change the return value of these views to pass the
-`resulting `logged_in`` value to the template, e.g.:
+We'll then change the return value of these views to pass the `resulting
+`logged_in`` value to the template, e.g.:
.. ignore-next-block
.. code-block:: python
diff --git a/docs/tutorials/wiki2/basiclayout.rst b/docs/tutorials/wiki2/basiclayout.rst
index c73009eb0..4d3496788 100644
--- a/docs/tutorials/wiki2/basiclayout.rst
+++ b/docs/tutorials/wiki2/basiclayout.rst
@@ -2,10 +2,9 @@
Basic Layout
============
-The starter files generated by the ``pyramid_routesalchemy`` template
-are basic, but they provide a good orientation for the high-level
-patterns common to most :term:`url dispatch` -based :app:`Pyramid`
-projects.
+The starter files generated by the ``pyramid_routesalchemy`` template are
+basic, but they provide a good orientation for the high-level patterns common
+to most :term:`url dispatch` -based :app:`Pyramid` projects.
The source code for this tutorial stage can be browsed at
`http://github.com/Pylons/pyramid/tree/master/docs/tutorials/wiki2/src/basiclayout/
@@ -32,9 +31,9 @@ First we need some imports to support later code:
:linenos:
:language: py
-Next we define the main function and create a SQLAlchemy database
-engine from the ``sqlalchemy.`` prefixed settings in the ``development.ini`
-`file's ``[app:tutorial]`` section. This will be a URI (something like
+Next we define the main function and create a SQLAlchemy database engine from
+the ``sqlalchemy.`` prefixed settings in the ``development.ini`` file's
+``[app:tutorial]`` section. This will be a URI (something like
``sqlite://``):
.. literalinclude:: src/basiclayout/tutorial/__init__.py
@@ -55,10 +54,10 @@ The next step is to construct a :term:`Configurator`:
:lines: 11
:language: py
-``settings`` is passed as a keyword argument with the dictionary values
-passed by PasteDeploy as the ``settings`` argument. This will be a
-dictionary of settings parsed by PasteDeploy, which contains
-deployment-related values such as ``reload_templates``,
+``settings`` is passed to the Configurator as a keyword argument with the
+dictionary values passed by PasteDeploy as the ``**settings`` argument. This
+will be a dictionary of settings parsed from the ``.ini`` file, which
+contains deployment-related values such as ``reload_templates``,
``db_string``, etc.
We now can call :meth:`pyramid.config.Configurator.add_static_view` with the
@@ -85,18 +84,19 @@ used when the URL is ``/``:
:lines: 13-14
:language: py
-Since this route has a ``pattern`` equalling
-``/`` it is the "default" route. The argument named ``view`` with the
-value ``tutorial.views.my_view`` is the dotted name to a *function* we
-write (generated by the ``pyramid_routesalchemy`` template) that is given
-a ``request`` object and which returns a response or a dictionary.
+Since this route has a ``pattern`` equalling ``/`` it is the route that will
+be called when the URL ``/`` is visted, e.g. ``http://localhost:6543/``. The
+argument named ``view`` with the value ``tutorial.views.my_view`` is the
+dotted name to a *function* we write (generated by the
+``pyramid_routesalchemy`` template) that is given a ``request`` object and
+which returns a response or a dictionary.
-You will use :meth:`pyramid.config.Configurator.add_route` statements
-in a :term:`URL dispatch` based application to map URLs to code. This
-route also names a ``view_renderer``, which is a template which lives in
-the ``templates`` subdirectory of the package. When the
-``tutorial.views.my_view`` view returns a dictionary, a :term:`renderer`
-will use this template to create a response.
+You will use :meth:`pyramid.config.Configurator.add_route` statements in a
+:term:`URL dispatch` based application to map URLs to code. This route also
+names a ``view_renderer``, which is a template which lives in the
+``templates`` subdirectory of the package. When the
+``tutorial.views.my_view`` view returns a dictionary, a :term:`renderer` will
+use this template to create a response.
Fimnally, we use the :meth:`pyramid.config.Configurator.make_wsgi_app`
method to return a :term:`WSGI` application:
@@ -105,7 +105,7 @@ method to return a :term:`WSGI` application:
:lines: 15
:language: py
-Our final __init__.py file will look like this:
+Our final ``__init__.py`` file will look like this:
.. literalinclude:: src/basiclayout/tutorial/__init__.py
:linenos:
@@ -148,12 +148,11 @@ To give a simple example of a model class, we define one named ``MyModel``:
:linenos:
:language: py
-Our sample model has an ``__init__`` that takes a two arguments
-(``name``, and ``value``).
-It stores these values as ``self.name`` and ``self.value`` within
-the ``__init__`` function itself. The ``MyModel`` class also has a
-``__tablename__`` attribute. This informs SQLAlchemy which table
-to use to store the data representing instances of this class.
+Our sample model has an ``__init__`` that takes a two arguments (``name``,
+and ``value``). It stores these values as ``self.name`` and ``self.value``
+within the ``__init__`` function itself. The ``MyModel`` class also has a
+``__tablename__`` attribute. This informs SQLAlchemy which table to use to
+store the data representing instances of this class.
Next we define a function named ``populate`` which adds a single
model instance into our SQL storage and commits a transaction:
diff --git a/docs/tutorials/wiki2/definingmodels.rst b/docs/tutorials/wiki2/definingmodels.rst
index 117442a1c..7e8555190 100644
--- a/docs/tutorials/wiki2/definingmodels.rst
+++ b/docs/tutorials/wiki2/definingmodels.rst
@@ -37,28 +37,27 @@ SQLAlchemy models are easier to use than directly-mapped ones.
:language: python
As you can see, our ``Page`` class has a class level attribute
-``__tablename__`` which equals the string ``pages``.
-This means that SQLAlchemy will store our wiki
-data in a SQL table named ``pages``. Our Page class will also have
-class-level attributes named ``id``, ``pagename`` and ``data`` (all instances
-of :class:`sqlalchemy.Column`). These will map to columns in the ``pages``
-table. The ``id`` attribute will be the primary key in the table. The
-``name`` attribute will be a text attribute, each value of which needs to be
-unique within the column. The ``data`` attribute is a text attribute that
-will hold the body of each page.
-
-We'll also remove our ``populate`` function. We'll inline the
-populate step into ``initialize_sql``, changing our ``initialize_sql``
-function to add a FrontPage object to our database at startup time.
+``__tablename__`` which equals the string ``pages``. This means that
+SQLAlchemy will store our wiki data in a SQL table named ``pages``. Our Page
+class will also have class-level attributes named ``id``, ``pagename`` and
+``data`` (all instances of :class:`sqlalchemy.Column`). These will map to
+columns in the ``pages`` table. The ``id`` attribute will be the primary key
+in the table. The ``name`` attribute will be a text attribute, each value of
+which needs to be unique within the column. The ``data`` attribute is a text
+attribute that will hold the body of each page.
+
+We'll also remove our ``populate`` function. We'll inline the populate step
+into ``initialize_sql``, changing our ``initialize_sql`` function to add a
+FrontPage object to our database at startup time.
.. literalinclude:: src/models/tutorial/models.py
:pyobject: initialize_sql
:linenos:
:language: python
-Here, we're using a slightly different binding syntax. It is
-otherwise largely the same as the ``initialize_sql`` in the
-paster-generated ``models.py``.
+Here, we're using a slightly different binding syntax. It is otherwise
+largely the same as the ``initialize_sql`` in the paster-generated
+``models.py``.
Our DBSession assignment stays the same as the original generated
``models.py``.
@@ -76,11 +75,10 @@ something like this:
Viewing the Application in a Browser
------------------------------------
-We can't. At this point, our system is in a "non-runnable" state;
-we'll need to change view-related files in the next chapter to be able
-to start the application successfully. If you try to start the
-application, you'll wind up with a Python traceback on your console
-that ends with this exception:
+We can't. At this point, our system is in a "non-runnable" state; we'll need
+to change view-related files in the next chapter to be able to start the
+application successfully. If you try to start the application, you'll wind
+up with a Python traceback on your console that ends with this exception:
.. code-block:: text
diff --git a/docs/tutorials/wiki2/definingviews.rst b/docs/tutorials/wiki2/definingviews.rst
index 3fa9bbccd..874c49d4c 100644
--- a/docs/tutorials/wiki2/definingviews.rst
+++ b/docs/tutorials/wiki2/definingviews.rst
@@ -2,10 +2,10 @@
Defining Views
==============
-A :term:`view callable` in a :term:`url dispatch` -based
-:app:`Pyramid` application is typically a simple Python function that
-accepts a single parameter named :term:`request`. A view callable is
-assumed to return a :term:`response` object.
+A :term:`view callable` in a :term:`url dispatch` -based :app:`Pyramid`
+application is typically a simple Python function that accepts a single
+parameter named :term:`request`. A view callable is assumed to return a
+:term:`response` object.
.. note:: A :app:`Pyramid` view can also be defined as callable
which accepts *two* arguments: a :term:`context` and a
@@ -23,11 +23,11 @@ assumed to return a :term:`response` object.
The request passed to every view that is called as the result of a route
match has an attribute named ``matchdict`` that contains the elements placed
into the URL by the ``pattern`` of a ``route`` statement. For instance, if a
-call to :meth:`pyramid.config.Configurator.add_route` in
-``__init__.py`` had the pattern ``{one}/{two}``, and the URL at
-``http://example.com/foo/bar`` was invoked, matching this pattern, the
-matchdict dictionary attached to the request passed to the view would have a
-``one`` key with the value ``foo`` and a ``two`` key with the value ``bar``.
+call to :meth:`pyramid.config.Configurator.add_route` in ``__init__.py`` had
+the pattern ``{one}/{two}``, and the URL at ``http://example.com/foo/bar``
+was invoked, matching this pattern, the matchdict dictionary attached to the
+request passed to the view would have a ``one`` key with the value ``foo``
+and a ``two`` key with the value ``bar``.
The source code for this tutorial stage can be browsed at
`http://github.com/Pylons/pyramid/tree/master/docs/tutorials/wiki2/src/views/
@@ -36,13 +36,13 @@ The source code for this tutorial stage can be browsed at
Declaring Dependencies in Our ``setup.py`` File
===============================================
-The view code in our application will depend on a package which is not
-a dependency of the original "tutorial" application. The original
-"tutorial" application was generated by the ``paster create`` 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
-``install_requires`` parameter in the ``setup`` function.
+The view code in our application will depend on a package which is not a
+dependency of the original "tutorial" application. The original "tutorial"
+application was generated by the ``paster create`` 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 ``install_requires`` parameter in the
+``setup`` function.
Our resulting ``setup.py`` should look like so:
@@ -58,45 +58,43 @@ Our resulting ``setup.py`` should look like so:
Adding View Functions
=====================
-We'll get rid of our ``my_view`` view function in our ``views.py``
-file. It's only an example and isn't relevant to our application.
+We'll get rid of our ``my_view`` view function in our ``views.py`` file.
+It's only an example and isn't relevant to our application.
Then we're going to add four :term:`view callable` functions to our
-``views.py`` module. One view callable (named ``view_wiki``) will
-display the wiki itself (it will answer on the root URL), another
-named ``view_page`` will display an individual page, another named
-``add_page`` will allow a page to be added, and a final view callable
-named ``edit_page`` will allow a page to be edited. We'll describe
-each one briefly and show the resulting ``views.py`` file afterward.
+``views.py`` module. One view callable (named ``view_wiki``) will display
+the wiki itself (it will answer on the root URL), another named ``view_page``
+will display an individual page, another named ``add_page`` will allow a page
+to be added, and a final view callable named ``edit_page`` will allow a page
+to be edited. We'll describe each one briefly and show the resulting
+``views.py`` file afterward.
.. note::
- There is nothing special about the filename ``views.py``. A project
- may 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.
+ There is nothing special about the filename ``views.py``. A project may
+ 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.
The ``view_wiki`` view function
-------------------------------
-The ``view_wiki`` function will respond as the :term:`default view` of
-a ``Wiki`` model object. It always redirects to a URL which
-represents the path to our "FrontPage".
+The ``view_wiki`` function will respond as the :term:`default view` of a
+``Wiki`` model object. It always redirects to a URL which represents the
+path to our "FrontPage".
.. literalinclude:: src/views/tutorial/views.py
:pyobject: view_wiki
:linenos:
:language: python
-It returns an instance of the
-:class:`pyramid.httpexceptions.HTTPFound` class (instances of which
-implement the WebOb :term:`response` interface), It will use the
-:func:`pyramid.url.route_url` API to construct a URL to the
-``FrontPage`` page (e.g. ``http://localhost:6543/FrontPage``), and
-will use it as the "location" of the HTTPFound response, forming an
-HTTP redirect.
+The ``view_wiki`` function returns an instance of the
+:class:`pyramid.httpexceptions.HTTPFound` class (instances of which implement
+the WebOb :term:`response` interface), It will use the
+:func:`pyramid.url.route_url` API to construct a URL to the ``FrontPage``
+page (e.g. ``http://localhost:6543/FrontPage``), and will use it as the
+"location" of the HTTPFound response, forming an HTTP redirect.
The ``view_page`` view function
-------------------------------
@@ -114,76 +112,70 @@ compiled regular expression.
:language: python
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, the ``check``
-function generates a view link to be used as the substitution value
-and returns it. If the wiki does not already contain a page with with
-the matched WikiWord name, the function generates an "add" link as the
-substitution value and returns it.
-
-As a result, the ``content`` variable is now a fully formed bit of
-HTML containing various view and add links for WikiWords based on the
-content of our current page object.
-
-We then generate an edit URL (because it's easier to do here than in
-the template), and we return a dictionary with a number of arguments.
-The fact that this view returns a dictionary (as opposed to a
-:term:`response` object) is a cue to :app:`Pyramid` that it should
-try to use a :term:`renderer` associated with the view configuration
-to render a template. In our case, the template which will be
-rendered will be the ``templates/view.pt`` template, as per the
-configuration put into effect in ``__init__.py``.
+``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, the ``check`` function generates a view
+link to be used as the substitution value and returns it. If the wiki does
+not already contain a page with with the matched WikiWord name, the function
+generates an "add" link as the substitution value and returns it.
+
+As a result, the ``content`` variable is now a fully formed bit of HTML
+containing various view and add links for WikiWords based on the content of
+our current page object.
+
+We then generate an edit URL (because it's easier to do here than in the
+template), and we return a dictionary with a number of arguments. The fact
+that this view returns a dictionary (as opposed to a :term:`response` object)
+is a cue to :app:`Pyramid` that it should try to use a :term:`renderer`
+associated with the view configuration to render a template. In our case,
+the template which will be rendered will be the ``templates/view.pt``
+template, as per the configuration put into effect in ``__init__.py``.
The ``add_page`` view function
------------------------------
-The ``add_page`` function will be 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. It also acts as a handler for the form that is generated
-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.
+The ``add_page`` function will be 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. It also acts as a
+handler for the form that is generated 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
:pyobject: add_page
: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 ``pagename``
-value in the matchdict will be ``SomeName``.
+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 ``pagename`` value in
+the matchdict will be ``SomeName``.
If the view execution is *not* a result of a form submission (if 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 template use as the form post URL during rendering. We're
-lazy here, so we're trying to use the same template
-(``templates/edit.pt``) for the add view as well as the page edit
-view, so we create a dummy Page object in order to satisfy the edit
-form's desire to have *some* page object exposed as ``page``, and
-:app:`Pyramid` will render the template associated with this view
-to a response.
-
-If the view execution *is* a result of a form submission (if the
-expression ``'form.submitted' in request.params`` is ``True``), we
-scrape the page body from the form data, create a Page object using
-the name in the matchdict ``pagename``, and obtain the page body from
-the request, and save it into the database using ``session.add``. We
-then redirect back to the ``view_page`` view (the :term:`default view`
-for a Page) for the newly created page.
+expression ``'form.submitted' in request.params`` is ``False``), the view
+callable renders a template. To do so, it generates a "save url" which the
+template use as the form post URL during rendering. We're lazy here, so
+we're trying to use the same template (``templates/edit.pt``) for the add
+view as well as the page edit view, so we create a dummy Page object in order
+to satisfy the edit form's desire to have *some* page object exposed as
+``page``, and :app:`Pyramid` will render the template associated with this
+view to a response.
+
+If the view execution *is* a result of a form submission (if the expression
+``'form.submitted' in request.params`` is ``True``), we scrape the page body
+from the form data, create a Page object using the name in the matchdict
+``pagename``, and obtain the page body from the request, and save it into the
+database using ``session.add``. We then redirect back to the ``view_page``
+view (the :term:`default view` for a Page) for the newly created page.
The ``edit_page`` view function
-------------------------------
-The ``edit_page`` function will be 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.
+The ``edit_page`` function will be 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
:pyobject: edit_page
@@ -191,10 +183,9 @@ wants to edit.
:language: python
If the view execution is *not* a result of a form submission (if the
-expression ``'form.submitted' in request.params`` is ``False``), the
-view simply renders the edit form, passing the request, the page
-object, and a save_url which will be used as the action of the
-generated form.
+expression ``'form.submitted' in request.params`` is ``False``), the view
+simply renders the edit form, passing the request, the page object, and a
+save_url which will be used as the action of the generated form.
If the view execution *is* a result of a form submission (if the expression
``'form.submitted' in request.params`` is ``True``), the view grabs the
@@ -222,15 +213,14 @@ The views we've added all reference a :term:`template`. Each template is a
The ``view.pt`` Template
------------------------
-The ``view.pt`` template is used for viewing a single wiki page. It
-is used by the ``view_page`` view function. It should have a div that
-is "structure replaced" with the ``content`` value provided by the
-view. It should also have a link on the rendered page that points at
-the "edit" URL (the URL which invokes the ``edit_page`` view for the
-page being viewed).
+The ``view.pt`` template is used for viewing a single wiki page. It is used
+by the ``view_page`` view function. It should have a div that is "structure
+replaced" with the ``content`` value provided by the view. It should also
+have a link on the rendered page that points at the "edit" URL (the URL which
+invokes the ``edit_page`` view for the page being viewed).
-Once we're done with the ``view.pt`` template, it will look a lot like
-the below:
+Once we're done with the ``view.pt`` template, it will look a lot like the
+below:
.. literalinclude:: src/views/tutorial/templates/view.pt
:language: xml
@@ -248,13 +238,12 @@ the below:
The ``edit.pt`` Template
------------------------
-The ``edit.pt`` template is used for adding and editing a wiki page.
-It is used by the ``add_page`` and ``edit_page`` view functions. It
-should display a page containing a form that POSTs back to the
-"save_url" argument supplied by the view. The form should have a
-"body" textarea field (the page data), and a submit button that has
-the name "form.submitted". The textarea in the form should be filled
-with any existing page data when it is rendered.
+The ``edit.pt`` template is used for adding and editing a wiki page. It is
+used by the ``add_page`` and ``edit_page`` view functions. It should display
+a page containing a form that POSTs back to the "save_url" argument supplied
+by the view. The form should have a "body" textarea field (the page data),
+and a submit button that has the name "form.submitted". The textarea in the
+form should be filled with any existing page data when it is rendered.
Once we're done with the ``edit.pt`` template, it will look a lot like
the below:
@@ -267,8 +256,8 @@ 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
+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
<http://github.com/Pylons/pyramid/blob/master/docs/tutorials/wiki2/src/views/tutorial/static/pylons.css>`_.
This CSS file will be accessed via
@@ -276,8 +265,8 @@ e.g. ``http://localhost:6543/static/pylons.css`` by virtue of the call to
``add_static_view`` directive we've made in the ``__init__`` 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.
Mapping Views to URLs in ``__init__.py``
========================================