diff options
| author | Michael Merickel <michael@merickel.org> | 2015-10-21 16:57:52 -0500 |
|---|---|---|
| committer | Michael Merickel <michael@merickel.org> | 2015-10-21 16:57:52 -0500 |
| commit | adb9377a963d7fdc7b7bf616740fb5dd2e40b2bf (patch) | |
| tree | 1038d03a21148607c79f740f0b32b147929251bf /docs/tutorials/wiki2/definingviews.rst | |
| parent | 452fdbef94bb29560497ec8a9ccbc3b9c2ecd2dd (diff) | |
| parent | d4221720b8409eafb65b301562be327af0196c7e (diff) | |
| download | pyramid-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.rst | 227 |
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 ">", 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 ">", 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`. |
