diff options
Diffstat (limited to 'docs/narr/project.rst')
| -rw-r--r-- | docs/narr/project.rst | 124 |
1 files changed, 78 insertions, 46 deletions
diff --git a/docs/narr/project.rst b/docs/narr/project.rst index f41e155e7..fb5a241db 100644 --- a/docs/narr/project.rst +++ b/docs/narr/project.rst @@ -525,21 +525,27 @@ The ``myproject`` project we've generated has the following directory structure: .. code-block:: text - myproject/ + myproject ├── .coveragerc + ├── .gitignore ├── CHANGES.txt ├── MANIFEST.in ├── myproject │ ├── __init__.py + │ ├── routes.py │ ├── static │ │ ├── pyramid-16x16.png │ │ ├── pyramid.png │ │ └── theme.css │ ├── templates + │ │ ├── 404.jinja2 │ │ ├── layout.jinja2 │ │ └── mytemplate.jinja2 │ ├── tests.py - │ └── views.py + │ └── views + │ ├── __init__.py + │ ├── default.py + │ └── notfound.py ├── README.txt ├── development.ini ├── production.ini @@ -557,6 +563,8 @@ describe, run, and test your application. #. ``.coveragerc`` configures coverage when running tests. +#. ``.gitignore`` tells git which files and directories to ignore from source code version control. + #. ``CHANGES.txt`` describes the changes you've made to the application. It is conventionally written in :term:`reStructuredText` format. @@ -810,7 +818,9 @@ The ``myproject`` :term:`package` lives inside the ``myproject`` #. A ``tests.py`` module, which contains unit test code for the application. -#. A ``views.py`` module, which contains view code for the application. +#. A ``views`` package, which contains view code for the application. + +#. A ``static`` directory, which contains static files, including images and CSS. These are purely conventions established by the cookiecutter. :app:`Pyramid` doesn't insist that you name things in any particular way. However, it's @@ -848,31 +858,53 @@ also informs Python that the directory which contains it is a *package*. Line 8 adds support for Jinja2 templating bindings, allowing us to specify renderers with the ``.jinja2`` extension. - Line 9 registers a static view, which will serve up the files from the - ``myproject:static`` :term:`asset specification` (the ``static`` directory - of the ``myproject`` package). + Line 9 includes the ``routes.py`` module. - Line 10 adds a :term:`route` to the configuration. This route is later used - by a view in the ``views`` module. - - Line 11 calls ``config.scan()``, which picks up view registrations declared + Line 10 calls ``config.scan()``, which picks up view registrations declared elsewhere in the package (in this case, in the ``views.py`` module). - Line 12 returns a :term:`WSGI` application to the caller of the function + Line 11 returns a :term:`WSGI` application to the caller of the function (Pyramid's pserve). + +.. index:: + single: routes.py + +.. _routes_py: + +``routes.py`` +~~~~~~~~~~~~~ + +The ``routes.py`` module gets included by the ``main`` function in our ``__init__.py``. +It registers a view and a route. + +.. literalinclude:: myproject/myproject/routes.py + :language: python + :linenos: + +Line 2 registers a static view, which will serve up the files from the ``myproject:static`` :term:`asset specification` (the ``static`` directory of the ``myproject`` package). + +Line 3 adds a :term:`route` to the configuration. This route is later used by a view in the ``views`` module. + + .. index:: single: views.py -``views.py`` -~~~~~~~~~~~~ +``views`` package +~~~~~~~~~~~~~~~~~ Much of the heavy lifting in a :app:`Pyramid` application is done by *view callables*. A :term:`view callable` is the main tool of a :app:`Pyramid` web application developer; it is a bit of code which accepts a :term:`request` and which returns a :term:`response`. -.. literalinclude:: myproject/myproject/views.py +Our project has a ``views`` package by virtue of it being a directory containing an ``__init__.py`` file. +This ``__init__.py`` file happens to have no content, although it could as a project develops. + +We have two view modules in the ``views`` package. +Let's look at ``default.py``. + +.. literalinclude:: myproject/myproject/views/default.py :language: python :linenos: @@ -880,17 +912,17 @@ Lines 4-6 define and register a :term:`view callable` named ``my_view``. The function named ``my_view`` is decorated with a ``view_config`` decorator (which is processed by the ``config.scan()`` line in our ``__init__.py``). The view_config decorator asserts that this view be found when a :term:`route` -named ``home`` is matched. In our case, because our ``__init__.py`` maps the +named ``home`` is matched. In our case, because our ``routes.py`` maps the route named ``home`` to the URL pattern ``/``, this route will match when a visitor visits the root URL. The view_config decorator also names a ``renderer``, which in this case is a template that will be used to render the result of the view callable. This particular view declaration points at -``templates/mytemplate.pt``, which is an :term:`asset specification` that -specifies the ``mytemplate.pt`` file within the ``templates`` directory of the +``../templates/mytemplate.jinja2``, which is an :term:`asset specification` that +specifies the ``mytemplate.jinja2`` file within the ``templates`` directory of the ``myproject`` package. The asset specification could have also been specified -as ``myproject:templates/mytemplate.pt``; the leading package name and colon is +as ``myproject:templates/mytemplate.jinja2``; the leading package name and colon is optional. The template file pointed to is a :term:`Jinja2` template -file (``templates/my_template.jinja2``). +file (``templates/mytemplate.jinja2``). This view callable function is handed a single piece of information: the :term:`request`. The *request* is an instance of the :term:`WebOb` ``Request`` @@ -903,6 +935,15 @@ the HTML in a :term:`response`. .. note:: Dictionaries provide values to :term:`template`\s. +Now let's look at ``notfound.py``. + +.. literalinclude:: myproject/myproject/views/notfound.py + :language: python + :linenos: + +This file is similar to ``default.py``. +It merely returns a ``404`` response status and an empty dictionary to the template at ``../templates/404.jinja2``. + .. note:: When the application is run with the cookiecutter's :ref:`default development.ini <myproject_ini>` configuration, :ref:`logging is set up <myproject_ini_logging>` to aid debugging. If an exception is raised, @@ -964,7 +1005,7 @@ This is the base layout content. It contains a single marker for content block. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This is the content :term:`Jinja2` template that exists in the project. It is referenced by the call to ``@view_config`` as the ``renderer`` -of the ``my_view`` view callable in the ``views.py`` file. See +of the ``my_view`` view callable in the ``views/default.py`` file. See :ref:`views_which_use_a_renderer` for more information about renderers. It inherits ("extends") the HTML provided by ``layout.jinja2``, replacing the content block with its own content. .. literalinclude:: myproject/myproject/templates/mytemplate.jinja2 @@ -976,6 +1017,18 @@ functions themselves. See :ref:`templates_used_directly` and :ref:`templates_used_as_renderers`. +``templates/404.jinja2`` +~~~~~~~~~~~~~~~~~~~~~~~~ + +This template is similar to ``mytemplate.jinja2``, but with a few differences. +It is referenced by the call to ``@notfound_view_config`` as the ``renderer`` of the ``notfound_view`` view callable in the ``views/notfound.py`` file. +It inherits the HTML provided by ``layout.jinja2``, replacing the content block with its own content. + +.. literalinclude:: myproject/myproject/templates/404.jinja2 + :language: jinja + :linenos: + + .. index:: single: tests.py @@ -1015,32 +1068,11 @@ cookiecutter, you can decide to lay your code out any way you see fit. For example, the configuration method named :meth:`~pyramid.config.Configurator.add_view` requires you to pass a :term:`dotted Python name` or a direct object reference as the class or -function to be used as a view. By default, the ``starter`` cookiecutter would have -you add view functions to the ``views.py`` module in your package. However, you -might be more comfortable creating a ``views`` *directory*, and adding a single -file for each view. - -If your project package name was ``myproject`` and you wanted to arrange all -your views in a Python subpackage within the ``myproject`` :term:`package` -named ``views`` instead of within a single ``views.py`` file, you might do the -following. - -- Create a ``views`` directory inside your ``myproject`` package directory (the - same directory which holds ``views.py``). - -- Create a file within the new ``views`` directory named ``__init__.py``. (It - can be empty. This just tells Python that the ``views`` directory is a - *package*.) - -- *Move* the content from the existing ``views.py`` file to a file inside the - new ``views`` directory named, say, ``blog.py``. Because the ``templates`` - directory remains in the ``myproject`` package, the template :term:`asset - specification` values in ``blog.py`` must now be fully qualified with the - project's package name (``myproject:templates/blog.pt``). - -You can then continue to add view callable functions to the ``blog.py`` module, -but you can also add other ``.py`` files which contain view callable functions -to the ``views`` directory. As long as you use the ``@view_config`` directive +function to be used as a view. +By default, the ``starter`` cookiecutter would have you create a ``views`` directory, and add a single file for each view or collection of related views. +However, you might be more comfortable creating a single ``views.py`` module in your package and add view functions to it. + +Whatever structure you prefer, as long as you use the ``@view_config`` directive to register views in conjunction with ``config.scan()``, they will be picked up automatically when the application is restarted. |
