summaryrefslogtreecommitdiff
path: root/docs/tutorials/wiki2
diff options
context:
space:
mode:
authorChris McDonough <chrism@plope.com>2013-02-09 19:15:07 -0500
committerChris McDonough <chrism@plope.com>2013-02-09 19:15:07 -0500
commitacf115391088770ae434d222179fd22a693bfe46 (patch)
tree442d33920cd6d20ccb7ce3cff3344fd851448d0d /docs/tutorials/wiki2
parent6313e0dd97e22b8c897293cd8d5f2f145637f49f (diff)
parent7fe736bf57696aa62c8b0d84e62ad486d0f88f40 (diff)
downloadpyramid-acf115391088770ae434d222179fd22a693bfe46.tar.gz
pyramid-acf115391088770ae434d222179fd22a693bfe46.tar.bz2
pyramid-acf115391088770ae434d222179fd22a693bfe46.zip
Merge branch 'master' of github.com:Pylons/pyramid
Diffstat (limited to 'docs/tutorials/wiki2')
-rw-r--r--docs/tutorials/wiki2/authorization.rst34
-rw-r--r--docs/tutorials/wiki2/background.rst5
-rw-r--r--docs/tutorials/wiki2/basiclayout.rst51
-rw-r--r--docs/tutorials/wiki2/definingmodels.rst39
-rw-r--r--docs/tutorials/wiki2/definingviews.rst43
-rw-r--r--docs/tutorials/wiki2/design.rst2
-rw-r--r--docs/tutorials/wiki2/index.rst6
-rw-r--r--docs/tutorials/wiki2/installation.rst54
-rw-r--r--docs/tutorials/wiki2/src/authorization/README.txt13
-rw-r--r--docs/tutorials/wiki2/src/authorization/development.ini20
-rw-r--r--docs/tutorials/wiki2/src/authorization/setup.py10
-rw-r--r--docs/tutorials/wiki2/src/authorization/tutorial/__init__.py2
-rw-r--r--docs/tutorials/wiki2/src/authorization/tutorial/models.py1
-rw-r--r--docs/tutorials/wiki2/src/authorization/tutorial/scripts/initializedb.py4
-rw-r--r--docs/tutorials/wiki2/src/authorization/tutorial/tests.py1
-rw-r--r--docs/tutorials/wiki2/src/basiclayout/README.txt13
-rw-r--r--docs/tutorials/wiki2/src/basiclayout/development.ini20
-rw-r--r--docs/tutorials/wiki2/src/basiclayout/production.ini12
-rw-r--r--docs/tutorials/wiki2/src/basiclayout/setup.py9
-rw-r--r--docs/tutorials/wiki2/src/basiclayout/tutorial/__init__.py2
-rw-r--r--docs/tutorials/wiki2/src/basiclayout/tutorial/models.py2
-rw-r--r--docs/tutorials/wiki2/src/basiclayout/tutorial/scripts/initializedb.py4
-rw-r--r--docs/tutorials/wiki2/src/basiclayout/tutorial/templates/mytemplate.pt2
-rw-r--r--docs/tutorials/wiki2/src/basiclayout/tutorial/tests.py1
-rw-r--r--docs/tutorials/wiki2/src/basiclayout/tutorial/views.py28
-rw-r--r--docs/tutorials/wiki2/src/models/README.txt13
-rw-r--r--docs/tutorials/wiki2/src/models/development.ini20
-rw-r--r--docs/tutorials/wiki2/src/models/setup.py9
-rw-r--r--docs/tutorials/wiki2/src/models/tutorial/__init__.py2
-rw-r--r--docs/tutorials/wiki2/src/models/tutorial/models.py2
-rw-r--r--docs/tutorials/wiki2/src/models/tutorial/scripts/initializedb.py4
-rw-r--r--docs/tutorials/wiki2/src/models/tutorial/tests.py1
-rw-r--r--docs/tutorials/wiki2/src/models/tutorial/views.py28
-rw-r--r--docs/tutorials/wiki2/src/tests/README.txt13
-rw-r--r--docs/tutorials/wiki2/src/tests/development.ini20
-rw-r--r--docs/tutorials/wiki2/src/tests/setup.py8
-rw-r--r--docs/tutorials/wiki2/src/tests/tutorial/__init__.py2
-rw-r--r--docs/tutorials/wiki2/src/tests/tutorial/models.py1
-rw-r--r--docs/tutorials/wiki2/src/tests/tutorial/scripts/initializedb.py4
-rw-r--r--docs/tutorials/wiki2/src/tests/tutorial/tests.py8
-rw-r--r--docs/tutorials/wiki2/src/tests/tutorial/views.py13
-rw-r--r--docs/tutorials/wiki2/src/views/README.txt13
-rw-r--r--docs/tutorials/wiki2/src/views/development.ini20
-rw-r--r--docs/tutorials/wiki2/src/views/setup.py9
-rw-r--r--docs/tutorials/wiki2/src/views/tutorial/__init__.py1
-rw-r--r--docs/tutorials/wiki2/src/views/tutorial/models.py2
-rw-r--r--docs/tutorials/wiki2/src/views/tutorial/scripts/initializedb.py4
-rw-r--r--docs/tutorials/wiki2/src/views/tutorial/tests.py1
-rw-r--r--docs/tutorials/wiki2/tests.rst3
49 files changed, 374 insertions, 205 deletions
diff --git a/docs/tutorials/wiki2/authorization.rst b/docs/tutorials/wiki2/authorization.rst
index 1ddf8c82d..5ede26920 100644
--- a/docs/tutorials/wiki2/authorization.rst
+++ b/docs/tutorials/wiki2/authorization.rst
@@ -14,7 +14,7 @@ anyone with access to the server to view pages.
We will also add a login page and a logout link on all the
pages. The login page will be shown when a user is denied
-access to any of the views that require a permission, instead of
+access to any of the views that require permission, instead of
a default "403 Forbidden" page.
We will implement the access control with the following steps:
@@ -36,9 +36,6 @@ Then we will add the login and logout feature:
* Add a "Logout" link to be shown when logged in and viewing or editing a page
(``view.pt``, ``edit.pt``).
-The source code for this tutorial stage can be browsed at
-`http://github.com/Pylons/pyramid/tree/1.3-branch/docs/tutorials/wiki2/src/authorization/
-<http://github.com/Pylons/pyramid/tree/1.3-branch/docs/tutorials/wiki2/src/authorization/>`_.
Access Control
--------------
@@ -62,7 +59,7 @@ returns one of these values:
- If the userid *does not* exist in the system, it will
return ``None``.
-For example, ``groupfinder('editor', request )`` returns ['group:editor'],
+For example, ``groupfinder('editor', request )`` returns ``['group:editor']``,
``groupfinder('viewer', request)`` returns [], and ``groupfinder('admin', request)``
returns ``None``. We will use ``groupfinder()`` as an :term:`authentication policy`
"callback" that will provide the :term:`principal` or principals
@@ -86,7 +83,7 @@ statement at the head:
Add the following class definition:
.. literalinclude:: src/authorization/tutorial/models.py
- :lines: 35-39
+ :lines: 36-40
:linenos:
:language: python
@@ -112,7 +109,7 @@ parameter to our :term:`Configurator` constructor, that points to
the class we created above:
.. literalinclude:: src/authorization/tutorial/__init__.py
- :lines: 23-24
+ :lines: 24-25
:linenos:
:emphasize-lines: 2
:language: python
@@ -144,19 +141,19 @@ add these import statements:
Now add those policies to the configuration:
.. literalinclude:: src/authorization/tutorial/__init__.py
- :lines: 20-26
+ :lines: 21-27
:linenos:
:emphasize-lines: 1-3,6-7
:language: python
(Only the highlighted lines need to be added.)
-We are enabling an ``AuthTktAuthenticationPolicy``, it is based in an
-auth ticket that may be included in the request, and an
-``ACLAuthorizationPolicy`` that uses an ACL to determine the allow or deny
-outcome for a view.
+We are enabling an ``AuthTktAuthenticationPolicy``, which is based in an
+auth ticket that may be included in the request.
+We are also enabling an ``ACLAuthorizationPolicy``, which uses an ACL to
+determine the *allow* or *deny* outcome for a view.
-Note that the :class:`pyramid.authentication.AuthTktAuthenticationPolicy`
+Note that the :class:`~pyramid.authentication.AuthTktAuthenticationPolicy`
constructor accepts two arguments: ``secret`` and ``callback``. ``secret`` is
a string representing an encryption key used by the "authentication ticket"
machinery represented by this policy: it is required. The ``callback`` is the
@@ -206,7 +203,7 @@ Go back to ``tutorial/tutorial/__init__.py`` and add these two
routes:
.. literalinclude:: src/authorization/tutorial/__init__.py
- :lines: 29-30
+ :lines: 30-31
:linenos:
:language: python
@@ -303,9 +300,8 @@ like this:
(Only the highlighted line needs to be added.)
-:meth:`~pyramid.security.authenticated_userid()` will return None
-if the user is not authenticated, or some user id it the user
-is authenticated.
+The :meth:`~pyramid.security.authenticated_userid` method will return None
+if the user is not authenticated.
Add a "Logout" link when logged in
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -333,7 +329,7 @@ when we're done:
.. literalinclude:: src/authorization/tutorial/__init__.py
:linenos:
- :emphasize-lines: 2-3,7,23-24,20-26,29-30
+ :emphasize-lines: 2-3,7,21-23,25-27,30-31
:language: python
(Only the highlighted lines need to be added.)
@@ -343,7 +339,7 @@ when we're done:
.. literalinclude:: src/authorization/tutorial/models.py
:linenos:
- :emphasize-lines: 1-4,35-39
+ :emphasize-lines: 1-4,36-40
:language: python
(Only the highlighted lines need to be added.)
diff --git a/docs/tutorials/wiki2/background.rst b/docs/tutorials/wiki2/background.rst
index 9933adc27..1f9582903 100644
--- a/docs/tutorials/wiki2/background.rst
+++ b/docs/tutorials/wiki2/background.rst
@@ -11,9 +11,8 @@ To code along with this tutorial, the developer will need a UNIX
machine with development tools (Mac OS X with XCode, any Linux or BSD
variant, etc) *or* a Windows system of any kind.
-.. warning::
+.. note::
- This tutorial has been written for Python 2. It is unlikely to work
- without modification under Python 3.
+ This tutorial runs on both Python 2 and 3 without modification.
Have fun!
diff --git a/docs/tutorials/wiki2/basiclayout.rst b/docs/tutorials/wiki2/basiclayout.rst
index dbd130c36..68be4ee7c 100644
--- a/docs/tutorials/wiki2/basiclayout.rst
+++ b/docs/tutorials/wiki2/basiclayout.rst
@@ -6,9 +6,6 @@ The starter files generated by the ``alchemy`` scaffold are very 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/1.3-branch/docs/tutorials/wiki2/src/basiclayout/
-<http://github.com/Pylons/pyramid/tree/1.3-branch/docs/tutorials/wiki2/src/basiclayout/>`_.
Application Configuration with ``__init__.py``
----------------------------------------------
@@ -45,24 +42,23 @@ When you invoke the ``pserve development.ini`` command, the ``main`` function
above is executed. It accepts some settings and returns a :term:`WSGI`
application. (See :ref:`startup_chapter` for more about ``pserve``.)
-The main function first creates a SQLAlchemy database engine using
+The main function first creates a :term:`SQLAlchemy` database engine using
``engine_from_config`` from the ``sqlalchemy.`` prefixed settings in the
``development.ini`` file's ``[app:main]`` section. This will be a URI
(something like ``sqlite://``):
.. literalinclude:: src/basiclayout/tutorial/__init__.py
- :lines: 12
- :linenos:
+ :lines: 13
:language: py
``main`` then initializes our SQLAlchemy session object, passing it the
engine:
.. literalinclude:: src/basiclayout/tutorial/__init__.py
- :lines: 13
+ :lines: 14
:language: py
-``main`` subsequently initializes our SQLAlchemy declarative Base object,
+``main`` subsequently initializes our SQLAlchemy declarative ``Base`` object,
assigning the engine we created to the ``bind`` attribute of it's
``metadata`` object. This allows table definitions done imperatively
(instead of declaratively, via a class statement) to work. We won't use any
@@ -71,13 +67,13 @@ forgotten about this tutorial, you won't be left scratching your head when it
doesn't work.
.. literalinclude:: src/basiclayout/tutorial/__init__.py
- :lines: 14
+ :lines: 15
:language: py
The next step of ``main`` is to construct a :term:`Configurator` object:
.. literalinclude:: src/basiclayout/tutorial/__init__.py
- :lines: 15
+ :lines: 16
:language: py
``settings`` is passed to the Configurator as a keyword argument with the
@@ -90,15 +86,15 @@ deployment-related values such as ``pyramid.reload_templates``,
two arguments: ``static`` (the name), and ``static`` (the path):
.. literalinclude:: src/basiclayout/tutorial/__init__.py
- :lines: 16
+ :lines: 17
:language: py
This registers a static resource view which will match any URL that starts
-with the prefix ``/static`` (by virtue of the first argument to add_static
-view). This will serve up static resources for us from within the ``static``
-directory of our ``tutorial`` package, in this case, via
+with the prefix ``/static`` (by virtue of the first argument to
+``add_static_view``). This will serve up static resources for us from within
+the ``static`` directory of our ``tutorial`` package, in this case, via
``http://localhost:6543/static/`` and below (by virtue of the second argument
-to add_static_view). With this declaration, we're saying that any URL that
+to ``add_static_view``). With this declaration, we're saying that any URL that
starts with ``/static`` should go to the static view; any remainder of its
path (e.g. the ``/foo`` in ``/static/foo``) will be used to compose a path to
a static file resource, such as a CSS file.
@@ -108,20 +104,21 @@ via the :meth:`pyramid.config.Configurator.add_route` method that will be
used when the URL is ``/``:
.. literalinclude:: src/basiclayout/tutorial/__init__.py
- :lines: 17
+ :lines: 18
:language: py
Since this route has a ``pattern`` equalling ``/`` it is the route that will
be matched when the URL ``/`` is visited, e.g. ``http://localhost:6543/``.
-``main`` next calls the ``scan`` method of the configurator, which will
-recursively scan our ``tutorial`` package, looking for ``@view_config`` (and
+``main`` next calls the ``scan`` method of the configurator
+(:meth:`pyramid.config.Configurator.scan`), which will recursively scan our
+``tutorial`` package, looking for ``@view_config`` (and
other special) decorators. When it finds a ``@view_config`` decorator, a
view configuration will be registered, which will allow one of our
application URLs to be mapped to some code.
.. literalinclude:: src/basiclayout/tutorial/__init__.py
- :lines: 18
+ :lines: 19
:language: py
Finally, ``main`` is finished configuring things, so it uses the
@@ -129,7 +126,7 @@ Finally, ``main`` is finished configuring things, so it uses the
:term:`WSGI` application:
.. literalinclude:: src/basiclayout/tutorial/__init__.py
- :lines: 19
+ :lines: 20
:language: py
View Declarations via ``views.py``
@@ -171,6 +168,12 @@ application. Without being processed by ``scan``, the decorator effectively
does nothing. ``@view_config`` is inert without being detected via a
:term:`scan`.
+The sample ``my_view()`` created by the scaffold uses a ``try:`` and ``except:``
+clause, to detect if there is a problem accessing the project database and
+provide an alternate error response. That response will include the text
+shown at the end of the file, which will be displayed in the browser to
+inform the user about possible actions to take to solve the problem.
+
Content Models with ``models.py``
---------------------------------
@@ -191,11 +194,10 @@ Let's examine this in detail. First, we need some imports to support later code:
:linenos:
:language: py
-Next we set up a SQLAlchemy "DBSession" object:
+Next we set up a SQLAlchemy ``DBSession`` object:
.. literalinclude:: src/basiclayout/tutorial/models.py
:lines: 16
- :linenos:
:language: py
``scoped_session`` and ``sessionmaker`` are standard SQLAlchemy helpers.
@@ -224,8 +226,9 @@ To give a simple example of a model class, we define one named ``MyModel``:
:linenos:
:language: py
-Our example model has an ``__init__`` that takes a two arguments (``name``,
-and ``value``). It stores these values as ``self.name`` and ``self.value``
+Our example model has an ``__init__`` method 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.
diff --git a/docs/tutorials/wiki2/definingmodels.rst b/docs/tutorials/wiki2/definingmodels.rst
index 1653faf4a..bd1cb00d7 100644
--- a/docs/tutorials/wiki2/definingmodels.rst
+++ b/docs/tutorials/wiki2/definingmodels.rst
@@ -2,20 +2,17 @@
Defining the Domain Model
=========================
-The first change we'll make to our stock pcreate-generated application will
+The first change we'll make to our stock ``pcreate``-generated application will
be to define a :term:`domain model` constructor representing a wiki page.
We'll do this inside our ``models.py`` file.
-The source code for this tutorial stage can be browsed at
-`http://github.com/Pylons/pyramid/tree/1.3-branch/docs/tutorials/wiki2/src/models/
-<http://github.com/Pylons/pyramid/tree/1.3-branch/docs/tutorials/wiki2/src/models/>`_.
Making Edits to ``models.py``
-----------------------------
.. note::
- There is nothing automagically special about the filename ``models.py``. A
+ There is nothing special about the filename ``models.py``. A
project may have many models throughout its codebase in arbitrarily-named
files. Files implementing models often have ``model`` in their filenames
(or they may live in a Python subpackage of your application package named
@@ -27,11 +24,11 @@ following:
.. literalinclude:: src/models/tutorial/models.py
:linenos:
:language: py
- :emphasize-lines: 19-21,24,26,28
+ :emphasize-lines: 20-22,25,27,29
(The highlighted lines are the ones that need to be changed.)
-The first thing we've done is to do is remove the stock ``MyModel`` class
+The first thing we've done is remove the stock ``MyModel`` class
from the generated ``models.py`` file. The ``MyModel`` class is only a
sample and we're not going to use it.
@@ -46,8 +43,8 @@ this class inherits from an instance of
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``, ``name`` and
+SQLAlchemy will store our wiki data in a SQL table named ``pages``. Our
+``Page`` class will also have class-level attributes named ``id``, ``name`` 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
@@ -73,29 +70,19 @@ following:
.. literalinclude:: src/models/tutorial/scripts/initializedb.py
:linenos:
:language: python
- :emphasize-lines: 14,34
+ :emphasize-lines: 14,36
(Only the highlighted lines need to be changed.)
-Reinitializing the Database
----------------------------
+Installing the Project and re-initializing the Database
+-------------------------------------------------------
+
+Redo the steps in :ref:`installing_project_in_dev_mode`.
Because our model has changed, in order to reinitialize the database, we need
to rerun the ``initialize_tutorial_db`` command to pick up the changes you've made
-to both the models.py file and to the initializedb.py file. From the root of the
-``tutorial`` project, directory execute the following commands.
-
-On UNIX:
-
-.. code-block:: text
-
- $ ../bin/initialize_tutorial_db development.ini
-
-On Windows:
-
-.. code-block:: text
-
- c:\pyramidtut\tutorial> ..\Scripts\initialize_tutorial_db development.ini
+to both the models.py file and to the initializedb.py file.
+See :ref:`initialize_db_wiki2` for instructions.
Success will look something like this::
diff --git a/docs/tutorials/wiki2/definingviews.rst b/docs/tutorials/wiki2/definingviews.rst
index a54996e3c..e83a88198 100644
--- a/docs/tutorials/wiki2/definingviews.rst
+++ b/docs/tutorials/wiki2/definingviews.rst
@@ -16,9 +16,6 @@ instance, if a call to :meth:`pyramid.config.Configurator.add_route` in
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/1.3-branch/docs/tutorials/wiki2/src/views/
-<http://github.com/Pylons/pyramid/tree/1.3-branch/docs/tutorials/wiki2/src/views/>`_.
Declaring Dependencies in Our ``setup.py`` File
===============================================
@@ -26,7 +23,7 @@ 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 ``pcreate`` command; it doesn't know
-about our custom application requirements.
+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()``.
@@ -123,14 +120,14 @@ the :class:`pyramid.interfaces.IResponse` interface like
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.
+is used 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 object) as HTML. Then it substitutes an
+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.
@@ -139,12 +136,12 @@ compiled regular expression.
:linenos:
:language: python
-The curried ``check()`` function is used as the first argument to
+The ``check()`` function 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
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, ``check()``
+not already contain a page with the matched WikiWord name, ``check()``
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
@@ -181,6 +178,13 @@ 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
``'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
+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
expression ``'form.submitted' in request.params`` is ``False``), the view
callable renders a template. To do so, it generates a "save url" which the
@@ -191,13 +195,6 @@ in order to satisfy the edit form's desire to have *some* page object
exposed as ``page``. :app:`Pyramid` will render the template associated
with this view to a response.
-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
-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.
-
The ``edit_page`` view function
-------------------------------
@@ -212,17 +209,17 @@ matching the name of the page the user wants to edit.
:linenos:
:language: python
-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.
-
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
+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
================
@@ -342,7 +339,7 @@ something like:
.. literalinclude:: src/views/tutorial/__init__.py
:linenos:
:language: python
- :emphasize-lines: 17-20
+ :emphasize-lines: 18-21
(The highlighted lines are the ones that need to be added or edited.)
@@ -358,7 +355,7 @@ each of the following URLs, check that the result is as expected:
of the FrontPage page object.
- ``http://localhost:6543/FrontPage`` in a browser invokes
- the ``view_page`` view of the front page page object.
+ 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.
@@ -366,7 +363,7 @@ each of the following URLs, check that the result is as expected:
- ``http://localhost:6543/add_page/SomePageName`` in a
browser invokes the add view for a page.
-- To generate an error, visit ``http://localhost:6543/add_page`` which
+- 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`.
diff --git a/docs/tutorials/wiki2/design.rst b/docs/tutorials/wiki2/design.rst
index 6e41e00aa..c56d7fecf 100644
--- a/docs/tutorials/wiki2/design.rst
+++ b/docs/tutorials/wiki2/design.rst
@@ -9,7 +9,7 @@ tutorial.
Overall
-------
-We choose to use ``reStructuredText`` markup in the wiki text. Translation
+We choose to use :term:`reStructuredText` markup in the wiki text. Translation
from reStructuredText to HTML is provided by the widely used ``docutils``
Python module. We will add this module in the dependency list on the project
``setup.py`` file.
diff --git a/docs/tutorials/wiki2/index.rst b/docs/tutorials/wiki2/index.rst
index bbc2fb96e..0a614cb23 100644
--- a/docs/tutorials/wiki2/index.rst
+++ b/docs/tutorials/wiki2/index.rst
@@ -9,9 +9,9 @@ tutorial is finished, the developer will have created a basic Wiki
application with authentication.
For cut and paste purposes, the source code for all stages of this
-tutorial can be browsed at
-`https://github.com/Pylons/pyramid/tree/1.3-branch/docs/tutorials/wiki2/src
-<https://github.com/Pylons/pyramid/tree/1.3-branch/docs/tutorials/wiki2/src>`_.
+tutorial can be browsed on GitHub at `docs/tutorials/wiki2/src
+<https://github.com/Pylons/pyramid/tree/master/docs/tutorials/wiki2/src>`_,
+which corresponds to the same location if you have Pyramid sources.
.. toctree::
:maxdepth: 2
diff --git a/docs/tutorials/wiki2/installation.rst b/docs/tutorials/wiki2/installation.rst
index 6589a1557..9fa01d513 100644
--- a/docs/tutorials/wiki2/installation.rst
+++ b/docs/tutorials/wiki2/installation.rst
@@ -2,30 +2,22 @@
Installation
============
-This tutorial assumes that Python and virtualenv are already installed
-and working in your system. If you need help setting this up, you should
-refer to the chapters on :ref:`installing_chapter`.
-
Preparation
===========
-Please take the following steps to prepare for the tutorial. The
-steps are slightly different depending on whether you're using UNIX or
-Windows.
+Follow the steps in :ref:`installing_chapter`, but name the virtualenv
+directory ``pyramidtut``.
Preparation, UNIX
-----------------
#. Install SQLite3 and its development packages if you don't already
have them installed. Usually this is via your system's package
- manager. For example, on a Debian Linux system, do ``sudo apt-get
- install libsqlite3-dev``.
-
-#. Use your Python's virtualenv to make a workspace:
+ manager. On a Debian system, this would be:
.. code-block:: text
- $ path/to/my/Python-2.6/bin/virtualenv --no-site-packages pyramidtut
+ $ sudo apt-get install libsqlite3-dev
#. Switch to the ``pyramidtut`` directory:
@@ -33,35 +25,16 @@ Preparation, UNIX
$ cd pyramidtut
-#. Use ``easy_install`` to get :app:`Pyramid` and its direct
- dependencies installed:
-
- .. code-block:: text
-
- $ bin/easy_install pyramid
Preparation, Windows
--------------------
-#. Use your Python's virtualenv to make a workspace:
-
- .. code-block:: text
-
- c:\> c:\Python26\Scripts\virtualenv --no-site-packages pyramidtut
-
#. Switch to the ``pyramidtut`` directory:
.. code-block:: text
c:\> cd pyramidtut
-#. Use ``easy_install`` to get :app:`Pyramid` and its direct
- dependencies installed:
-
- .. code-block:: text
-
- c:\pyramidtut> Scripts\easy_install pyramid
-
.. _sql_making_a_project:
Making a Project
@@ -93,14 +66,17 @@ On Windows:
startup problems, try putting both the virtualenv and the project
into directories that do not contain spaces in their paths.
+
+.. _installing_project_in_dev_mode:
+
Installing the Project in "Development Mode"
============================================
In order to do development on the project easily, you must "register"
the project as a development egg in your workspace using the
-``setup.py develop`` command. In order to do so, cd to the "tutorial"
+``setup.py develop`` command. In order to do so, cd to the `tutorial`
directory you created in :ref:`sql_making_a_project`, and run the
-"setup.py develop" command using virtualenv Python interpreter.
+``setup.py develop`` command using the virtualenv Python interpreter.
On UNIX:
@@ -158,8 +134,8 @@ test`` does but provides additional "coverage" information, exposing
which lines of your project are "covered" (or not covered) by the
tests.
-To get this functionality working, we'll need to install a couple of
-other packages into our ``virtualenv``: ``nose`` and ``coverage``:
+To get this functionality working, we'll need to install the ``nose`` and
+``coverage`` packages into our ``virtualenv``:
On UNIX:
@@ -186,7 +162,7 @@ On Windows:
.. code-block:: text
- c:\pyramidtut\tutorial> ..\Scripts\nosetests --cover-package=tutorial ^
+ c:\pyramidtut\tutorial> ..\Scripts\nosetests --cover-package=tutorial \
--cover-erase --with-coverage
If successful, you will see output something like this::
@@ -208,6 +184,9 @@ If successful, you will see output something like this::
Looks like our package doesn't quite have 100% test coverage.
+
+.. _initialize_db_wiki2:
+
Initializing the Database
=========================
@@ -303,6 +282,9 @@ the following assumptions:
- you are willing to use :term:`url dispatch` to map URLs to code.
+- you want to use ``ZopeTransactionExtension`` and ``pyramid_tm`` to scope
+ sessions to requests
+
.. note::
:app:`Pyramid` supports any persistent storage mechanism (e.g. object
diff --git a/docs/tutorials/wiki2/src/authorization/README.txt b/docs/tutorials/wiki2/src/authorization/README.txt
index 6f851e9b7..141851285 100644
--- a/docs/tutorials/wiki2/src/authorization/README.txt
+++ b/docs/tutorials/wiki2/src/authorization/README.txt
@@ -1 +1,14 @@
tutorial README
+==================
+
+Getting Started
+---------------
+
+- cd <directory containing this file>
+
+- $venv/bin/python setup.py develop
+
+- $venv/bin/initialize_tutorial_db development.ini
+
+- $venv/bin/pserve development.ini
+
diff --git a/docs/tutorials/wiki2/src/authorization/development.ini b/docs/tutorials/wiki2/src/authorization/development.ini
index eb2f878c5..a9d53b296 100644
--- a/docs/tutorials/wiki2/src/authorization/development.ini
+++ b/docs/tutorials/wiki2/src/authorization/development.ini
@@ -1,3 +1,8 @@
+###
+# app configuration
+# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/environment.html
+###
+
[app:main]
use = egg:tutorial
@@ -12,12 +17,23 @@ pyramid.includes =
sqlalchemy.url = sqlite:///%(here)s/tutorial.sqlite
+# By default, the toolbar only appears for clients from IP addresses
+# '127.0.0.1' and '::1'.
+# debugtoolbar.hosts = 127.0.0.1 ::1
+
+###
+# wsgi server configuration
+###
+
[server:main]
use = egg:waitress#main
host = 0.0.0.0
port = 6543
-# Begin logging configuration
+###
+# logging configuration
+# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/logging.html
+###
[loggers]
keys = root, tutorial, sqlalchemy
@@ -53,5 +69,3 @@ formatter = generic
[formatter_generic]
format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s
-
-# End logging configuration
diff --git a/docs/tutorials/wiki2/src/authorization/setup.py b/docs/tutorials/wiki2/src/authorization/setup.py
index 2fd051927..36668dd33 100644
--- a/docs/tutorials/wiki2/src/authorization/setup.py
+++ b/docs/tutorials/wiki2/src/authorization/setup.py
@@ -13,17 +13,17 @@ requires = [
'pyramid_tm',
'pyramid_debugtoolbar',
'zope.sqlalchemy',
- 'docutils',
'waitress',
+ 'docutils',
]
setup(name='tutorial',
version='0.0',
description='tutorial',
- long_description=README + '\n\n' + CHANGES,
+ long_description=README + '\n\n' + CHANGES,
classifiers=[
"Programming Language :: Python",
- "Framework :: Pylons",
+ "Framework :: Pyramid",
"Topic :: Internet :: WWW/HTTP",
"Topic :: Internet :: WWW/HTTP :: WSGI :: Application",
],
@@ -35,8 +35,8 @@ setup(name='tutorial',
include_package_data=True,
zip_safe=False,
test_suite='tutorial',
- install_requires = requires,
- entry_points = """\
+ install_requires=requires,
+ entry_points="""\
[paste.app_factory]
main = tutorial:main
[console_scripts]
diff --git a/docs/tutorials/wiki2/src/authorization/tutorial/__init__.py b/docs/tutorials/wiki2/src/authorization/tutorial/__init__.py
index 76071173a..d08e55bf9 100644
--- a/docs/tutorials/wiki2/src/authorization/tutorial/__init__.py
+++ b/docs/tutorials/wiki2/src/authorization/tutorial/__init__.py
@@ -11,6 +11,7 @@ from .models import (
Base,
)
+
def main(global_config, **settings):
""" This function returns a Pyramid WSGI application.
"""
@@ -33,4 +34,3 @@ def main(global_config, **settings):
config.add_route('edit_page', '/{pagename}/edit_page')
config.scan()
return config.make_wsgi_app()
-
diff --git a/docs/tutorials/wiki2/src/authorization/tutorial/models.py b/docs/tutorials/wiki2/src/authorization/tutorial/models.py
index c3bdcbea5..91e5a0019 100644
--- a/docs/tutorials/wiki2/src/authorization/tutorial/models.py
+++ b/docs/tutorials/wiki2/src/authorization/tutorial/models.py
@@ -21,6 +21,7 @@ from zope.sqlalchemy import ZopeTransactionExtension
DBSession = scoped_session(sessionmaker(extension=ZopeTransactionExtension()))
Base = declarative_base()
+
class Page(Base):
""" The SQLAlchemy declarative model class for a Page object. """
__tablename__ = 'pages'
diff --git a/docs/tutorials/wiki2/src/authorization/tutorial/scripts/initializedb.py b/docs/tutorials/wiki2/src/authorization/tutorial/scripts/initializedb.py
index 03188e8ad..092e359ce 100644
--- a/docs/tutorials/wiki2/src/authorization/tutorial/scripts/initializedb.py
+++ b/docs/tutorials/wiki2/src/authorization/tutorial/scripts/initializedb.py
@@ -15,12 +15,14 @@ from ..models import (
Base,
)
+
def usage(argv):
cmd = os.path.basename(argv[0])
print('usage: %s <config_uri>\n'
- '(example: "%s development.ini")' % (cmd, cmd))
+ '(example: "%s development.ini")' % (cmd, cmd))
sys.exit(1)
+
def main(argv=sys.argv):
if len(argv) != 2:
usage(argv)
diff --git a/docs/tutorials/wiki2/src/authorization/tutorial/tests.py b/docs/tutorials/wiki2/src/authorization/tutorial/tests.py
index 31d2dc6d5..5dcee127b 100644
--- a/docs/tutorials/wiki2/src/authorization/tutorial/tests.py
+++ b/docs/tutorials/wiki2/src/authorization/tutorial/tests.py
@@ -1,5 +1,6 @@
import unittest
import transaction
+
from pyramid import testing
def _initTestingDB():
diff --git a/docs/tutorials/wiki2/src/basiclayout/README.txt b/docs/tutorials/wiki2/src/basiclayout/README.txt
index 6f851e9b7..141851285 100644
--- a/docs/tutorials/wiki2/src/basiclayout/README.txt
+++ b/docs/tutorials/wiki2/src/basiclayout/README.txt
@@ -1 +1,14 @@
tutorial README
+==================
+
+Getting Started
+---------------
+
+- cd <directory containing this file>
+
+- $venv/bin/python setup.py develop
+
+- $venv/bin/initialize_tutorial_db development.ini
+
+- $venv/bin/pserve development.ini
+
diff --git a/docs/tutorials/wiki2/src/basiclayout/development.ini b/docs/tutorials/wiki2/src/basiclayout/development.ini
index eb2f878c5..a9d53b296 100644
--- a/docs/tutorials/wiki2/src/basiclayout/development.ini
+++ b/docs/tutorials/wiki2/src/basiclayout/development.ini
@@ -1,3 +1,8 @@
+###
+# app configuration
+# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/environment.html
+###
+
[app:main]
use = egg:tutorial
@@ -12,12 +17,23 @@ pyramid.includes =
sqlalchemy.url = sqlite:///%(here)s/tutorial.sqlite
+# By default, the toolbar only appears for clients from IP addresses
+# '127.0.0.1' and '::1'.
+# debugtoolbar.hosts = 127.0.0.1 ::1
+
+###
+# wsgi server configuration
+###
+
[server:main]
use = egg:waitress#main
host = 0.0.0.0
port = 6543
-# Begin logging configuration
+###
+# logging configuration
+# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/logging.html
+###
[loggers]
keys = root, tutorial, sqlalchemy
@@ -53,5 +69,3 @@ formatter = generic
[formatter_generic]
format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s
-
-# End logging configuration
diff --git a/docs/tutorials/wiki2/src/basiclayout/production.ini b/docs/tutorials/wiki2/src/basiclayout/production.ini
index 4684d2f7a..fa94c1b3e 100644
--- a/docs/tutorials/wiki2/src/basiclayout/production.ini
+++ b/docs/tutorials/wiki2/src/basiclayout/production.ini
@@ -1,3 +1,8 @@
+###
+# app configuration
+# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/environment.html
+###
+
[app:main]
use = egg:tutorial
@@ -16,7 +21,10 @@ use = egg:waitress#main
host = 0.0.0.0
port = 6543
-# Begin logging configuration
+###
+# logging configuration
+# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/logging.html
+###
[loggers]
keys = root, tutorial, sqlalchemy
@@ -52,5 +60,3 @@ formatter = generic
[formatter_generic]
format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s
-
-# End logging configuration
diff --git a/docs/tutorials/wiki2/src/basiclayout/setup.py b/docs/tutorials/wiki2/src/basiclayout/setup.py
index 050de7299..a09bf756a 100644
--- a/docs/tutorials/wiki2/src/basiclayout/setup.py
+++ b/docs/tutorials/wiki2/src/basiclayout/setup.py
@@ -19,10 +19,10 @@ requires = [
setup(name='tutorial',
version='0.0',
description='tutorial',
- long_description=README + '\n\n' + CHANGES,
+ long_description=README + '\n\n' + CHANGES,
classifiers=[
"Programming Language :: Python",
- "Framework :: Pylons",
+ "Framework :: Pyramid",
"Topic :: Internet :: WWW/HTTP",
"Topic :: Internet :: WWW/HTTP :: WSGI :: Application",
],
@@ -34,12 +34,11 @@ setup(name='tutorial',
include_package_data=True,
zip_safe=False,
test_suite='tutorial',
- install_requires = requires,
- entry_points = """\
+ install_requires=requires,
+ entry_points="""\
[paste.app_factory]
main = tutorial:main
[console_scripts]
initialize_tutorial_db = tutorial.scripts.initializedb:main
""",
)
-
diff --git a/docs/tutorials/wiki2/src/basiclayout/tutorial/__init__.py b/docs/tutorials/wiki2/src/basiclayout/tutorial/__init__.py
index e39f619ed..aac7c5e69 100644
--- a/docs/tutorials/wiki2/src/basiclayout/tutorial/__init__.py
+++ b/docs/tutorials/wiki2/src/basiclayout/tutorial/__init__.py
@@ -6,6 +6,7 @@ from .models import (
Base,
)
+
def main(global_config, **settings):
""" This function returns a Pyramid WSGI application.
"""
@@ -17,4 +18,3 @@ def main(global_config, **settings):
config.add_route('home', '/')
config.scan()
return config.make_wsgi_app()
-
diff --git a/docs/tutorials/wiki2/src/basiclayout/tutorial/models.py b/docs/tutorials/wiki2/src/basiclayout/tutorial/models.py
index b6ac15429..aeeb9df64 100644
--- a/docs/tutorials/wiki2/src/basiclayout/tutorial/models.py
+++ b/docs/tutorials/wiki2/src/basiclayout/tutorial/models.py
@@ -16,6 +16,7 @@ from zope.sqlalchemy import ZopeTransactionExtension
DBSession = scoped_session(sessionmaker(extension=ZopeTransactionExtension()))
Base = declarative_base()
+
class MyModel(Base):
__tablename__ = 'models'
id = Column(Integer, primary_key=True)
@@ -25,4 +26,3 @@ class MyModel(Base):
def __init__(self, name, value):
self.name = name
self.value = value
-
diff --git a/docs/tutorials/wiki2/src/basiclayout/tutorial/scripts/initializedb.py b/docs/tutorials/wiki2/src/basiclayout/tutorial/scripts/initializedb.py
index 0e828465f..66feb3008 100644
--- a/docs/tutorials/wiki2/src/basiclayout/tutorial/scripts/initializedb.py
+++ b/docs/tutorials/wiki2/src/basiclayout/tutorial/scripts/initializedb.py
@@ -15,12 +15,14 @@ from ..models import (
Base,
)
+
def usage(argv):
cmd = os.path.basename(argv[0])
print('usage: %s <config_uri>\n'
- '(example: "%s development.ini")' % (cmd, cmd))
+ '(example: "%s development.ini")' % (cmd, cmd))
sys.exit(1)
+
def main(argv=sys.argv):
if len(argv) != 2:
usage(argv)
diff --git a/docs/tutorials/wiki2/src/basiclayout/tutorial/templates/mytemplate.pt b/docs/tutorials/wiki2/src/basiclayout/tutorial/templates/mytemplate.pt
index fbfa9870b..15ea6614f 100644
--- a/docs/tutorials/wiki2/src/basiclayout/tutorial/templates/mytemplate.pt
+++ b/docs/tutorials/wiki2/src/basiclayout/tutorial/templates/mytemplate.pt
@@ -70,7 +70,7 @@
</div>
</div>
<div id="footer">
- <div class="footer">&copy; Copyright 2008-2011, Agendaless Consulting.</div>
+ <div class="footer">&copy; Copyright 2008-2012, Agendaless Consulting.</div>
</div>
</body>
</html>
diff --git a/docs/tutorials/wiki2/src/basiclayout/tutorial/tests.py b/docs/tutorials/wiki2/src/basiclayout/tutorial/tests.py
index 653d061e4..57a775e0a 100644
--- a/docs/tutorials/wiki2/src/basiclayout/tutorial/tests.py
+++ b/docs/tutorials/wiki2/src/basiclayout/tutorial/tests.py
@@ -5,6 +5,7 @@ from pyramid import testing
from .models import DBSession
+
class TestMyView(unittest.TestCase):
def setUp(self):
self.config = testing.setUp()
diff --git a/docs/tutorials/wiki2/src/basiclayout/tutorial/views.py b/docs/tutorials/wiki2/src/basiclayout/tutorial/views.py
index 3e6abf2c2..4cfcae4af 100644
--- a/docs/tutorials/wiki2/src/basiclayout/tutorial/views.py
+++ b/docs/tutorials/wiki2/src/basiclayout/tutorial/views.py
@@ -1,11 +1,35 @@
+from pyramid.response import Response
from pyramid.view import view_config
+from sqlalchemy.exc import DBAPIError
+
from .models import (
DBSession,
MyModel,
)
+
@view_config(route_name='home', renderer='templates/mytemplate.pt')
def my_view(request):
- one = DBSession.query(MyModel).filter(MyModel.name=='one').first()
- return {'one':one, 'project':'tutorial'}
+ try:
+ one = DBSession.query(MyModel).filter(MyModel.name == 'one').first()
+ except DBAPIError:
+ return Response(conn_err_msg, content_type='text/plain', status_int=500)
+ return {'one': one, 'project': 'tutorial'}
+
+conn_err_msg = """\
+Pyramid is having a problem using your SQL database. The problem
+might be caused by one of the following things:
+
+1. You may need to run the "initialize_tutorial_db" script
+ to initialize your database tables. Check your virtual
+ environment's "bin" directory for this script and try to run it.
+
+2. Your database server may not be running. Check that the
+ database server referred to by the "sqlalchemy.url" setting in
+ your "development.ini" file is running.
+
+After you fix the problem, please restart the Pyramid application to
+try it again.
+"""
+
diff --git a/docs/tutorials/wiki2/src/models/README.txt b/docs/tutorials/wiki2/src/models/README.txt
index 6f851e9b7..141851285 100644
--- a/docs/tutorials/wiki2/src/models/README.txt
+++ b/docs/tutorials/wiki2/src/models/README.txt
@@ -1 +1,14 @@
tutorial README
+==================
+
+Getting Started
+---------------
+
+- cd <directory containing this file>
+
+- $venv/bin/python setup.py develop
+
+- $venv/bin/initialize_tutorial_db development.ini
+
+- $venv/bin/pserve development.ini
+
diff --git a/docs/tutorials/wiki2/src/models/development.ini b/docs/tutorials/wiki2/src/models/development.ini
index eb2f878c5..a9d53b296 100644
--- a/docs/tutorials/wiki2/src/models/development.ini
+++ b/docs/tutorials/wiki2/src/models/development.ini
@@ -1,3 +1,8 @@
+###
+# app configuration
+# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/environment.html
+###
+
[app:main]
use = egg:tutorial
@@ -12,12 +17,23 @@ pyramid.includes =
sqlalchemy.url = sqlite:///%(here)s/tutorial.sqlite
+# By default, the toolbar only appears for clients from IP addresses
+# '127.0.0.1' and '::1'.
+# debugtoolbar.hosts = 127.0.0.1 ::1
+
+###
+# wsgi server configuration
+###
+
[server:main]
use = egg:waitress#main
host = 0.0.0.0
port = 6543
-# Begin logging configuration
+###
+# logging configuration
+# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/logging.html
+###
[loggers]
keys = root, tutorial, sqlalchemy
@@ -53,5 +69,3 @@ formatter = generic
[formatter_generic]
format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s
-
-# End logging configuration
diff --git a/docs/tutorials/wiki2/src/models/setup.py b/docs/tutorials/wiki2/src/models/setup.py
index 050de7299..a09bf756a 100644
--- a/docs/tutorials/wiki2/src/models/setup.py
+++ b/docs/tutorials/wiki2/src/models/setup.py
@@ -19,10 +19,10 @@ requires = [
setup(name='tutorial',
version='0.0',
description='tutorial',
- long_description=README + '\n\n' + CHANGES,
+ long_description=README + '\n\n' + CHANGES,
classifiers=[
"Programming Language :: Python",
- "Framework :: Pylons",
+ "Framework :: Pyramid",
"Topic :: Internet :: WWW/HTTP",
"Topic :: Internet :: WWW/HTTP :: WSGI :: Application",
],
@@ -34,12 +34,11 @@ setup(name='tutorial',
include_package_data=True,
zip_safe=False,
test_suite='tutorial',
- install_requires = requires,
- entry_points = """\
+ install_requires=requires,
+ entry_points="""\
[paste.app_factory]
main = tutorial:main
[console_scripts]
initialize_tutorial_db = tutorial.scripts.initializedb:main
""",
)
-
diff --git a/docs/tutorials/wiki2/src/models/tutorial/__init__.py b/docs/tutorials/wiki2/src/models/tutorial/__init__.py
index e39f619ed..aac7c5e69 100644
--- a/docs/tutorials/wiki2/src/models/tutorial/__init__.py
+++ b/docs/tutorials/wiki2/src/models/tutorial/__init__.py
@@ -6,6 +6,7 @@ from .models import (
Base,
)
+
def main(global_config, **settings):
""" This function returns a Pyramid WSGI application.
"""
@@ -17,4 +18,3 @@ def main(global_config, **settings):
config.add_route('home', '/')
config.scan()
return config.make_wsgi_app()
-
diff --git a/docs/tutorials/wiki2/src/models/tutorial/models.py b/docs/tutorials/wiki2/src/models/tutorial/models.py
index 499396c5b..9a078d757 100644
--- a/docs/tutorials/wiki2/src/models/tutorial/models.py
+++ b/docs/tutorials/wiki2/src/models/tutorial/models.py
@@ -16,6 +16,7 @@ from zope.sqlalchemy import ZopeTransactionExtension
DBSession = scoped_session(sessionmaker(extension=ZopeTransactionExtension()))
Base = declarative_base()
+
class Page(Base):
""" The SQLAlchemy declarative model class for a Page object. """
__tablename__ = 'pages'
@@ -26,4 +27,3 @@ class Page(Base):
def __init__(self, name, data):
self.name = name
self.data = data
-
diff --git a/docs/tutorials/wiki2/src/models/tutorial/scripts/initializedb.py b/docs/tutorials/wiki2/src/models/tutorial/scripts/initializedb.py
index 03188e8ad..092e359ce 100644
--- a/docs/tutorials/wiki2/src/models/tutorial/scripts/initializedb.py
+++ b/docs/tutorials/wiki2/src/models/tutorial/scripts/initializedb.py
@@ -15,12 +15,14 @@ from ..models import (
Base,
)
+
def usage(argv):
cmd = os.path.basename(argv[0])
print('usage: %s <config_uri>\n'
- '(example: "%s development.ini")' % (cmd, cmd))
+ '(example: "%s development.ini")' % (cmd, cmd))
sys.exit(1)
+
def main(argv=sys.argv):
if len(argv) != 2:
usage(argv)
diff --git a/docs/tutorials/wiki2/src/models/tutorial/tests.py b/docs/tutorials/wiki2/src/models/tutorial/tests.py
index 653d061e4..57a775e0a 100644
--- a/docs/tutorials/wiki2/src/models/tutorial/tests.py
+++ b/docs/tutorials/wiki2/src/models/tutorial/tests.py
@@ -5,6 +5,7 @@ from pyramid import testing
from .models import DBSession
+
class TestMyView(unittest.TestCase):
def setUp(self):
self.config = testing.setUp()
diff --git a/docs/tutorials/wiki2/src/models/tutorial/views.py b/docs/tutorials/wiki2/src/models/tutorial/views.py
index 3e6abf2c2..4cfcae4af 100644
--- a/docs/tutorials/wiki2/src/models/tutorial/views.py
+++ b/docs/tutorials/wiki2/src/models/tutorial/views.py
@@ -1,11 +1,35 @@
+from pyramid.response import Response
from pyramid.view import view_config
+from sqlalchemy.exc import DBAPIError
+
from .models import (
DBSession,
MyModel,
)
+
@view_config(route_name='home', renderer='templates/mytemplate.pt')
def my_view(request):
- one = DBSession.query(MyModel).filter(MyModel.name=='one').first()
- return {'one':one, 'project':'tutorial'}
+ try:
+ one = DBSession.query(MyModel).filter(MyModel.name == 'one').first()
+ except DBAPIError:
+ return Response(conn_err_msg, content_type='text/plain', status_int=500)
+ return {'one': one, 'project': 'tutorial'}
+
+conn_err_msg = """\
+Pyramid is having a problem using your SQL database. The problem
+might be caused by one of the following things:
+
+1. You may need to run the "initialize_tutorial_db" script
+ to initialize your database tables. Check your virtual
+ environment's "bin" directory for this script and try to run it.
+
+2. Your database server may not be running. Check that the
+ database server referred to by the "sqlalchemy.url" setting in
+ your "development.ini" file is running.
+
+After you fix the problem, please restart the Pyramid application to
+try it again.
+"""
+
diff --git a/docs/tutorials/wiki2/src/tests/README.txt b/docs/tutorials/wiki2/src/tests/README.txt
index 6f851e9b7..141851285 100644
--- a/docs/tutorials/wiki2/src/tests/README.txt
+++ b/docs/tutorials/wiki2/src/tests/README.txt
@@ -1 +1,14 @@
tutorial README
+==================
+
+Getting Started
+---------------
+
+- cd <directory containing this file>
+
+- $venv/bin/python setup.py develop
+
+- $venv/bin/initialize_tutorial_db development.ini
+
+- $venv/bin/pserve development.ini
+
diff --git a/docs/tutorials/wiki2/src/tests/development.ini b/docs/tutorials/wiki2/src/tests/development.ini
index eb2f878c5..a9d53b296 100644
--- a/docs/tutorials/wiki2/src/tests/development.ini
+++ b/docs/tutorials/wiki2/src/tests/development.ini
@@ -1,3 +1,8 @@
+###
+# app configuration
+# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/environment.html
+###
+
[app:main]
use = egg:tutorial
@@ -12,12 +17,23 @@ pyramid.includes =
sqlalchemy.url = sqlite:///%(here)s/tutorial.sqlite
+# By default, the toolbar only appears for clients from IP addresses
+# '127.0.0.1' and '::1'.
+# debugtoolbar.hosts = 127.0.0.1 ::1
+
+###
+# wsgi server configuration
+###
+
[server:main]
use = egg:waitress#main
host = 0.0.0.0
port = 6543
-# Begin logging configuration
+###
+# logging configuration
+# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/logging.html
+###
[loggers]
keys = root, tutorial, sqlalchemy
@@ -53,5 +69,3 @@ formatter = generic
[formatter_generic]
format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s
-
-# End logging configuration
diff --git a/docs/tutorials/wiki2/src/tests/setup.py b/docs/tutorials/wiki2/src/tests/setup.py
index 0f58d8a18..3c2961fcc 100644
--- a/docs/tutorials/wiki2/src/tests/setup.py
+++ b/docs/tutorials/wiki2/src/tests/setup.py
@@ -21,10 +21,10 @@ requires = [
setup(name='tutorial',
version='0.0',
description='tutorial',
- long_description=README + '\n\n' + CHANGES,
+ long_description=README + '\n\n' + CHANGES,
classifiers=[
"Programming Language :: Python",
- "Framework :: Pylons",
+ "Framework :: Pyramid",
"Topic :: Internet :: WWW/HTTP",
"Topic :: Internet :: WWW/HTTP :: WSGI :: Application",
],
@@ -36,8 +36,8 @@ setup(name='tutorial',
include_package_data=True,
zip_safe=False,
test_suite='tutorial',
- install_requires = requires,
- entry_points = """\
+ install_requires=requires,
+ entry_points="""\
[paste.app_factory]
main = tutorial:main
[console_scripts]
diff --git a/docs/tutorials/wiki2/src/tests/tutorial/__init__.py b/docs/tutorials/wiki2/src/tests/tutorial/__init__.py
index 76071173a..d08e55bf9 100644
--- a/docs/tutorials/wiki2/src/tests/tutorial/__init__.py
+++ b/docs/tutorials/wiki2/src/tests/tutorial/__init__.py
@@ -11,6 +11,7 @@ from .models import (
Base,
)
+
def main(global_config, **settings):
""" This function returns a Pyramid WSGI application.
"""
@@ -33,4 +34,3 @@ def main(global_config, **settings):
config.add_route('edit_page', '/{pagename}/edit_page')
config.scan()
return config.make_wsgi_app()
-
diff --git a/docs/tutorials/wiki2/src/tests/tutorial/models.py b/docs/tutorials/wiki2/src/tests/tutorial/models.py
index c3bdcbea5..91e5a0019 100644
--- a/docs/tutorials/wiki2/src/tests/tutorial/models.py
+++ b/docs/tutorials/wiki2/src/tests/tutorial/models.py
@@ -21,6 +21,7 @@ from zope.sqlalchemy import ZopeTransactionExtension
DBSession = scoped_session(sessionmaker(extension=ZopeTransactionExtension()))
Base = declarative_base()
+
class Page(Base):
""" The SQLAlchemy declarative model class for a Page object. """
__tablename__ = 'pages'
diff --git a/docs/tutorials/wiki2/src/tests/tutorial/scripts/initializedb.py b/docs/tutorials/wiki2/src/tests/tutorial/scripts/initializedb.py
index 03188e8ad..092e359ce 100644
--- a/docs/tutorials/wiki2/src/tests/tutorial/scripts/initializedb.py
+++ b/docs/tutorials/wiki2/src/tests/tutorial/scripts/initializedb.py
@@ -15,12 +15,14 @@ from ..models import (
Base,
)
+
def usage(argv):
cmd = os.path.basename(argv[0])
print('usage: %s <config_uri>\n'
- '(example: "%s development.ini")' % (cmd, cmd))
+ '(example: "%s development.ini")' % (cmd, cmd))
sys.exit(1)
+
def main(argv=sys.argv):
if len(argv) != 2:
usage(argv)
diff --git a/docs/tutorials/wiki2/src/tests/tutorial/tests.py b/docs/tutorials/wiki2/src/tests/tutorial/tests.py
index 659862a09..3e96d0a82 100644
--- a/docs/tutorials/wiki2/src/tests/tutorial/tests.py
+++ b/docs/tutorials/wiki2/src/tests/tutorial/tests.py
@@ -1,7 +1,9 @@
import unittest
import transaction
+
from pyramid import testing
+
def _initTestingDB():
from sqlalchemy import create_engine
from tutorial.models import (
@@ -17,6 +19,7 @@ def _initTestingDB():
DBSession.add(model)
return DBSession
+
def _registerRoutes(config):
config.add_route('view_page', '{pagename}')
config.add_route('edit_page', '{pagename}/edit_page')
@@ -43,6 +46,7 @@ class PageModelTests(unittest.TestCase):
self.assertEqual(instance.name, 'SomeName')
self.assertEqual(instance.data, 'some data')
+
class ViewWikiTests(unittest.TestCase):
def setUp(self):
self.config = testing.setUp()
@@ -60,6 +64,7 @@ class ViewWikiTests(unittest.TestCase):
response = self._callFUT(request)
self.assertEqual(response.location, 'http://example.com/FrontPage')
+
class ViewPageTests(unittest.TestCase):
def setUp(self):
self.session = _initTestingDB()
@@ -93,6 +98,7 @@ class ViewPageTests(unittest.TestCase):
self.assertEqual(info['edit_url'],
'http://example.com/IDoExist/edit_page')
+
class AddPageTests(unittest.TestCase):
def setUp(self):
self.session = _initTestingDB()
@@ -125,6 +131,7 @@ class AddPageTests(unittest.TestCase):
page = self.session.query(Page).filter_by(name='AnotherPage').one()
self.assertEqual(page.data, 'Hello yo!')
+
class EditPageTests(unittest.TestCase):
def setUp(self):
self.session = _initTestingDB()
@@ -162,6 +169,7 @@ class EditPageTests(unittest.TestCase):
self.assertEqual(response.location, 'http://example.com/abc')
self.assertEqual(page.data, 'Hello yo!')
+
class FunctionalTests(unittest.TestCase):
viewer_login = '/login?login=viewer&password=viewer' \
diff --git a/docs/tutorials/wiki2/src/tests/tutorial/views.py b/docs/tutorials/wiki2/src/tests/tutorial/views.py
index 42ac0eb7f..0d085b0e2 100644
--- a/docs/tutorials/wiki2/src/tests/tutorial/views.py
+++ b/docs/tutorials/wiki2/src/tests/tutorial/views.py
@@ -37,14 +37,13 @@ def view_wiki(request):
permission='view')
def view_page(request):
pagename = request.matchdict['pagename']
- session = DBSession()
- page = session.query(Page).filter_by(name=pagename).first()
+ page = DBSession.query(Page).filter_by(name=pagename).first()
if page is None:
return HTTPNotFound('No such page')
def check(match):
word = match.group(1)
- exists = session.query(Page).filter_by(name=word).all()
+ exists = DBSession.query(Page).filter_by(name=word).all()
if exists:
view_url = request.route_url('view_page', pagename=word)
return '<a href="%s">%s</a>' % (view_url, word)
@@ -63,10 +62,9 @@ def view_page(request):
def add_page(request):
pagename = request.matchdict['pagename']
if 'form.submitted' in request.params:
- session = DBSession()
body = request.params['body']
page = Page(pagename, body)
- session.add(page)
+ DBSession.add(page)
return HTTPFound(location = request.route_url('view_page',
pagename=pagename))
save_url = request.route_url('add_page', pagename=pagename)
@@ -78,11 +76,10 @@ def add_page(request):
permission='edit')
def edit_page(request):
pagename = request.matchdict['pagename']
- session = DBSession()
- page = session.query(Page).filter_by(name=pagename).one()
+ page = DBSession.query(Page).filter_by(name=pagename).one()
if 'form.submitted' in request.params:
page.data = request.params['body']
- session.add(page)
+ DBSession.add(page)
return HTTPFound(location = request.route_url('view_page',
pagename=pagename))
return dict(
diff --git a/docs/tutorials/wiki2/src/views/README.txt b/docs/tutorials/wiki2/src/views/README.txt
index 6f851e9b7..141851285 100644
--- a/docs/tutorials/wiki2/src/views/README.txt
+++ b/docs/tutorials/wiki2/src/views/README.txt
@@ -1 +1,14 @@
tutorial README
+==================
+
+Getting Started
+---------------
+
+- cd <directory containing this file>
+
+- $venv/bin/python setup.py develop
+
+- $venv/bin/initialize_tutorial_db development.ini
+
+- $venv/bin/pserve development.ini
+
diff --git a/docs/tutorials/wiki2/src/views/development.ini b/docs/tutorials/wiki2/src/views/development.ini
index eb2f878c5..a9d53b296 100644
--- a/docs/tutorials/wiki2/src/views/development.ini
+++ b/docs/tutorials/wiki2/src/views/development.ini
@@ -1,3 +1,8 @@
+###
+# app configuration
+# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/environment.html
+###
+
[app:main]
use = egg:tutorial
@@ -12,12 +17,23 @@ pyramid.includes =
sqlalchemy.url = sqlite:///%(here)s/tutorial.sqlite
+# By default, the toolbar only appears for clients from IP addresses
+# '127.0.0.1' and '::1'.
+# debugtoolbar.hosts = 127.0.0.1 ::1
+
+###
+# wsgi server configuration
+###
+
[server:main]
use = egg:waitress#main
host = 0.0.0.0
port = 6543
-# Begin logging configuration
+###
+# logging configuration
+# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/logging.html
+###
[loggers]
keys = root, tutorial, sqlalchemy
@@ -53,5 +69,3 @@ formatter = generic
[formatter_generic]
format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s
-
-# End logging configuration
diff --git a/docs/tutorials/wiki2/src/views/setup.py b/docs/tutorials/wiki2/src/views/setup.py
index 34b578e21..36668dd33 100644
--- a/docs/tutorials/wiki2/src/views/setup.py
+++ b/docs/tutorials/wiki2/src/views/setup.py
@@ -20,10 +20,10 @@ requires = [
setup(name='tutorial',
version='0.0',
description='tutorial',
- long_description=README + '\n\n' + CHANGES,
+ long_description=README + '\n\n' + CHANGES,
classifiers=[
"Programming Language :: Python",
- "Framework :: Pylons",
+ "Framework :: Pyramid",
"Topic :: Internet :: WWW/HTTP",
"Topic :: Internet :: WWW/HTTP :: WSGI :: Application",
],
@@ -35,12 +35,11 @@ setup(name='tutorial',
include_package_data=True,
zip_safe=False,
test_suite='tutorial',
- install_requires = requires,
- entry_points = """\
+ install_requires=requires,
+ entry_points="""\
[paste.app_factory]
main = tutorial:main
[console_scripts]
initialize_tutorial_db = tutorial.scripts.initializedb:main
""",
)
-
diff --git a/docs/tutorials/wiki2/src/views/tutorial/__init__.py b/docs/tutorials/wiki2/src/views/tutorial/__init__.py
index 810e92f75..c95bfdbf8 100644
--- a/docs/tutorials/wiki2/src/views/tutorial/__init__.py
+++ b/docs/tutorials/wiki2/src/views/tutorial/__init__.py
@@ -6,6 +6,7 @@ from .models import (
Base,
)
+
def main(global_config, **settings):
""" This function returns a Pyramid WSGI application.
"""
diff --git a/docs/tutorials/wiki2/src/views/tutorial/models.py b/docs/tutorials/wiki2/src/views/tutorial/models.py
index 499396c5b..9a078d757 100644
--- a/docs/tutorials/wiki2/src/views/tutorial/models.py
+++ b/docs/tutorials/wiki2/src/views/tutorial/models.py
@@ -16,6 +16,7 @@ from zope.sqlalchemy import ZopeTransactionExtension
DBSession = scoped_session(sessionmaker(extension=ZopeTransactionExtension()))
Base = declarative_base()
+
class Page(Base):
""" The SQLAlchemy declarative model class for a Page object. """
__tablename__ = 'pages'
@@ -26,4 +27,3 @@ class Page(Base):
def __init__(self, name, data):
self.name = name
self.data = data
-
diff --git a/docs/tutorials/wiki2/src/views/tutorial/scripts/initializedb.py b/docs/tutorials/wiki2/src/views/tutorial/scripts/initializedb.py
index 03188e8ad..092e359ce 100644
--- a/docs/tutorials/wiki2/src/views/tutorial/scripts/initializedb.py
+++ b/docs/tutorials/wiki2/src/views/tutorial/scripts/initializedb.py
@@ -15,12 +15,14 @@ from ..models import (
Base,
)
+
def usage(argv):
cmd = os.path.basename(argv[0])
print('usage: %s <config_uri>\n'
- '(example: "%s development.ini")' % (cmd, cmd))
+ '(example: "%s development.ini")' % (cmd, cmd))
sys.exit(1)
+
def main(argv=sys.argv):
if len(argv) != 2:
usage(argv)
diff --git a/docs/tutorials/wiki2/src/views/tutorial/tests.py b/docs/tutorials/wiki2/src/views/tutorial/tests.py
index 31d2dc6d5..5dcee127b 100644
--- a/docs/tutorials/wiki2/src/views/tutorial/tests.py
+++ b/docs/tutorials/wiki2/src/views/tutorial/tests.py
@@ -1,5 +1,6 @@
import unittest
import transaction
+
from pyramid import testing
def _initTestingDB():
diff --git a/docs/tutorials/wiki2/tests.rst b/docs/tutorials/wiki2/tests.rst
index 6a7cbf62d..83df86b27 100644
--- a/docs/tutorials/wiki2/tests.rst
+++ b/docs/tutorials/wiki2/tests.rst
@@ -6,9 +6,6 @@ We will now add tests for the models and the views and a few functional
tests in the ``tests.py``. Tests ensure that an application works, and
that it continues to work after changes are made in the future.
-The source code for this tutorial stage can be browsed at
-`http://github.com/Pylons/pyramid/tree/1.3-branch/docs/tutorials/wiki2/src/tests/
-<http://github.com/Pylons/pyramid/tree/1.3-branch/docs/tutorials/wiki2/src/tests/>`_.
Testing the Models