summaryrefslogtreecommitdiff
path: root/docs/tutorials/wiki2/basiclayout.rst
diff options
context:
space:
mode:
authorChris McDonough <chrism@plope.com>2011-11-28 16:19:04 -0500
committerChris McDonough <chrism@plope.com>2011-11-28 16:19:04 -0500
commitdafb0b3271f525fb8552d155a4dd840ced1656c8 (patch)
tree786cccbf8f2287be8e2fa43afd33e503b5366739 /docs/tutorials/wiki2/basiclayout.rst
parent8786a5719950900ba7a8390323476076e737ac9e (diff)
parent14e5fa938b5354154f724101f444b1826b01aa3a (diff)
downloadpyramid-dafb0b3271f525fb8552d155a4dd840ced1656c8.tar.gz
pyramid-dafb0b3271f525fb8552d155a4dd840ced1656c8.tar.bz2
pyramid-dafb0b3271f525fb8552d155a4dd840ced1656c8.zip
merge master to feature.introspection
Diffstat (limited to 'docs/tutorials/wiki2/basiclayout.rst')
-rw-r--r--docs/tutorials/wiki2/basiclayout.rst195
1 files changed, 109 insertions, 86 deletions
diff --git a/docs/tutorials/wiki2/basiclayout.rst b/docs/tutorials/wiki2/basiclayout.rst
index db8ab1fbe..77658970d 100644
--- a/docs/tutorials/wiki2/basiclayout.rst
+++ b/docs/tutorials/wiki2/basiclayout.rst
@@ -2,82 +2,96 @@
Basic Layout
============
-The starter files generated by the ``alchemy`` scaffold 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 ``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/master/docs/tutorials/wiki2/src/basiclayout/
<http://github.com/Pylons/pyramid/tree/master/docs/tutorials/wiki2/src/basiclayout/>`_.
-App Startup with ``__init__.py``
---------------------------------
+Application Configuration with ``__init__.py``
+----------------------------------------------
A directory on disk can be turned into a Python :term:`package` by containing
an ``__init__.py`` file. Even if empty, this marks a directory as a Python
-package. We use ``__init__.py`` both as a package marker and to contain
-configuration code.
+package. We use ``__init__.py`` both as a marker indicating the directory
+it's contained within is a package, and to contain configuration code. Our
+``__init__.py`` file will look like this:
-The generated ``development.ini`` file is read by ``pserve`` which looks for
-the application module in the ``use`` variable of the ``app:main``
-section. The *entry point* is defined in the Setuptools configuration of this
-module, specifically in the ``setup.py`` file. For this tutorial, the *entry
-point* is defined as ``tutorial:main`` and points to a function named
-``main``.
+ .. literalinclude:: src/basiclayout/tutorial/__init__.py
+ :linenos:
+ :language: py
-First we need some imports to support later code:
+Let's go over this piece-by-piece. First, we need some imports to support
+later code:
.. literalinclude:: src/basiclayout/tutorial/__init__.py
:end-before: main
: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:main]`` section. This will be a URI (something like
-``sqlite://``):
+``__init__.py`` defines a function named ``main``. Here is the entirety of
+the ``main`` function we've defined in our ``__init__.py``:
+
+ .. literalinclude:: src/basiclayout/tutorial/__init__.py
+ :pyobject: main
+ :linenos:
+ :language: py
+
+When you invoke the ``pserve development.ini`` command, the ``main`` function
+above is executed. It accepts some settings and returns a :term:`WSGI`
+application. You can read :ref:`startup_chapter` for details about *how*
+this function is found and called when you run ``pserve``, but for purposes
+of brevity, we'll elide the details here.
+
+The main function first creates a 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: 6-9
+ :lines: 9
:linenos:
:language: py
-We then initialize our SQL database using SQLAlchemy, passing
-it the engine:
+``main`` then initializes our SQL database using SQLAlchemy, passing it the
+engine:
.. literalinclude:: src/basiclayout/tutorial/__init__.py
:lines: 10
:language: py
-The next step is to construct a :term:`Configurator`:
+The next step of ``main`` is to construct a :term:`Configurator` object:
.. literalinclude:: src/basiclayout/tutorial/__init__.py
:lines: 11
:language: py
``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 ``pyramid.reload_templates``,
+dictionary values passed as the ``**settings`` argument. This will be a
+dictionary of settings parsed from the ``.ini`` file, which contains
+deployment-related values such as ``pyramid.reload_templates``,
``db_string``, etc.
-We now can call :meth:`pyramid.config.Configurator.add_static_view` with the
-arguments ``static`` (the name), and ``tutorial:static`` (the path):
+``'main`` now calls :meth:`pyramid.config.Configurator.add_static_view` with
+two arguments: ``static`` (the name), and ``static`` (the path):
.. literalinclude:: src/basiclayout/tutorial/__init__.py
:lines: 12
:language: py
-This registers a static resource view which will match any URL that starts with
-``/static/``. 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. 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.
+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
+``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
+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.
-Using the configurator we can also register a :term:`route configuration`
+Using the configurator ``main`` also registers a :term:`route configuration`
via the :meth:`pyramid.config.Configurator.add_route` method that will be
used when the URL is ``/``:
@@ -88,44 +102,77 @@ used when the URL is ``/``:
Since this route has a ``pattern`` equalling ``/`` it is the route that will
be matched when the URL ``/`` is visted, e.g. ``http://localhost:6543/``.
-Mapping the ``home`` route to code is done by registering a view. You will
-use :meth:`pyramid.config.Configurator.add_view` in :term:`URL dispatch` to
-register views for the routes, mapping your patterns to code:
+``main`` next calls the ``scan`` method of the configurator, 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: 14-15
+ :lines: 14
:language: py
-The first positional ``add_view`` argument ``tutorial.views.my_view`` is the
-dotted name to a *function* we write (generated by the
-``alchemy`` scaffold) that is given a ``request`` object and
-which returns a response or a dictionary. This view also names a
-``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.
-
-Finally, we use the :meth:`pyramid.config.Configurator.make_wsgi_app`
-method to return a :term:`WSGI` application:
+Finally, ``main`` is finished configuring things, so it uses the
+:meth:`pyramid.config.Configurator.make_wsgi_app` method to return a
+:term:`WSGI` application:
.. literalinclude:: src/basiclayout/tutorial/__init__.py
- :lines: 16
+ :lines: 15
:language: py
-Our final ``__init__.py`` file will look like this:
+View Declarations via ``views.py``
+----------------------------------
- .. literalinclude:: src/basiclayout/tutorial/__init__.py
+Mapping a :term:`route` to code that will be executed when that route's
+pattern matches is done by registering a :term:`view configuration`. Our
+application uses the :meth:`pyramid.view.view_config` decorator to map view
+callables to each route, thereby mapping URL patterns to code.
+
+Here is the entirety of code in the ``views.py`` file within our package:
+
+ .. literalinclude:: src/basiclayout/tutorial/views.py
:linenos:
:language: py
+The important part to point out here is the ``@view_config`` decorator which
+sits atop the ``my_view`` function. In fact, ``@view_config`` is so
+important that we're going to ignore the rest of the code in the module at
+this point just to explain it. The ``@view_config`` decorator associates the
+function it decorates with a :term:`view configuration`. The view
+configuration names a ``route_name`` (``home``), and names a ``renderer``,
+which is a template which lives in the ``templates`` subdirectory of the
+package.
+
+As the result of this view configuration, when the pattern associated with
+the view named ``home`` is matched during a request, the function named
+``my_view`` will be executed. The the function named ``my_view`` returns a
+dictionary; the renderer will use the ``templates/mytemplate.pt`` template to
+create a response based on the values in the dictionary.
+
+Note that the decorated function named ``my_view`` accepts a single argument
+named ``request``. This is the standard call signature for a Pyramid
+:term:`view callable`.
+
+Remember in our ``__init__.py`` when we executed the
+:meth:`pyramid.config.Configurator.scan` method, e.g. ``config.scan()``? The
+purpose of calling the scan method was to find and process this
+``@view_config`` decorator in order to create a view configuration within our
+application. Without being processed by ``scan``, the decorator effectively
+does nothing. ``@view_config`` is inert without being detected via a
+:term:`scan`.
+
Content Models with ``models.py``
---------------------------------
-In a SQLAlchemy-based application, a *model* object is an object
-composed by querying the SQL database which backs an application.
-SQLAlchemy is an "object relational mapper" (an ORM). The
-``models.py`` file is where the ``alchemy`` scaffold
-put the classes that implement our models.
+In a SQLAlchemy-based application, a *model* object is an object composed by
+querying the SQL database. The ``models.py`` file is where the ``alchemy``
+scaffold put the classes that implement our models.
+
+Here is the complete source for ``models.py``:
+
+ .. literalinclude:: src/basiclayout/tutorial/models.py
+ :linenos:
+ :language: py
Let's take a look. First, we need some imports to support later code.
@@ -137,7 +184,7 @@ Let's take a look. First, we need some imports to support later code.
Next we set up a SQLAlchemy "DBSession" object:
.. literalinclude:: src/basiclayout/tutorial/models.py
- :lines: 15-16
+ :lines: 16
:linenos:
:language: py
@@ -161,30 +208,6 @@ 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:
-
- .. literalinclude:: src/basiclayout/tutorial/models.py
- :pyobject: populate
- :linenos:
- :language: py
-
-The function doesn't do a lot in this case, but it's there to illustrate
-how an application requiring many objects to be set up could work.
-
-Lastly we have a function named ``initialize_sql`` which receives a SQL
-database engine and binds it to our SQLAlchemy DBSession object. It also
-calls the ``populate`` function, to do initial database population. This
-is the initialization function that is called from __init__.py above.
-
- .. literalinclude:: src/basiclayout/tutorial/models.py
- :pyobject: initialize_sql
- :linenos:
- :language: py
-
-Here is the complete source for ``models.py``:
-
- .. literalinclude:: src/basiclayout/tutorial/models.py
- :linenos:
- :language: py
+That's about all there is to it to models, views, and initialization code in
+our stock application.