Dylan Jay
2011-08-25 d36b566a83addddb80d221aa042b828268f185f2
use routes in firstapp as they are more familar to most and put hello world on the front page
to make grab framework shoppers attention.
1 files added
3 files modified
190 ■■■■■ changed files
docs/glossary.rst 1 ●●●● patch | view | raw | blame | history
docs/index.rst 25 ●●●●● patch | view | raw | blame | history
docs/narr/firstapp.rst 152 ●●●●● patch | view | raw | blame | history
docs/narr/helloworld.py 12 ●●●●● patch | view | raw | blame | history
docs/glossary.rst
@@ -945,3 +945,4 @@
     log to a file, to UNIX syslog, to the Windows Event Log, or even to
     email. See its `documentation
     <https://docs.pylonsproject.org/projects/pyramid_exclog/dev/>`_.
docs/index.rst
@@ -9,6 +9,29 @@
<http://docs.pylonsproject.org/>`_.  It is licensed under a `BSD-like license
<http://repoze.org/license.html>`_.
Here is one of the simplest :app:`Pyramid` applications you can make.
.. code-block:: python
   from paste.httpserver import serve
   from pyramid.configuration import Configurator
   def hello_world(request):
      return 'Hello %(name)s!' % request.matchdict
   if __name__ == '__main__':
      config = Configurator()
      config.add_route('hello', '/hello/{name}')
      config.add_view(hello_world, route_name='hello')
      app = config.make_wsgi_app()
      serve(app, host='0.0.0.0')
See :ref:`firstapp_chapter` for a full explanation of how this :ref:`helloworld_imperative`
app works. Read the :ref:`narrative_documentation` to understand how :app:`Pyramid` is designed
to scale from these simple beginnings to handle the largest of web application needs. If your
familiar with other web frameworks you might want to look at :ref:`design_defense` to understand
why :app:`Pyramid` has been designed the way it has.
Front Matter
============
@@ -28,6 +51,8 @@
   whatsnew-1.1
   whatsnew-1.0
.. _narrative_documentation:
Narrative documentation
=======================
docs/narr/firstapp.rst
@@ -12,30 +12,14 @@
.. _helloworld_imperative:
Hello World, Goodbye World
--------------------------
Hello World
-----------
Here's one of the very simplest :app:`Pyramid` applications:
.. code-block:: python
.. literalinclude:: helloworld.py
   :linenos:
   from pyramid.config import Configurator
   from pyramid.response import Response
   from paste.httpserver import serve
   def hello_world(request):
       return Response('Hello world!')
   def goodbye_world(request):
       return Response('Goodbye world!')
   if __name__ == '__main__':
       config = Configurator()
       config.add_view(hello_world)
       config.add_view(goodbye_world, name='goodbye')
       app = config.make_wsgi_app()
       serve(app, host='0.0.0.0')
When this code is inserted into a Python script named ``helloworld.py`` and
executed by a Python interpreter which has the :app:`Pyramid` software
@@ -46,9 +30,8 @@
   $ python helloworld.py
   serving on 0.0.0.0:8080 view at http://127.0.0.1:8080
When port 8080 is visited by a browser on the root URL (``/``), the server
will simply serve up the text "Hello world!"  When visited by a browser on
the URL ``/goodbye``, the server will serve up the text "Goodbye world!"
When port 8080 is visited by a browser on the  URL (``/hello/world``), the server
will simply serve up the text "Hello world!"
Press ``Ctrl-C`` to stop the application.
@@ -61,20 +44,14 @@
The above ``helloworld.py`` script uses the following set of import
statements:
.. code-block:: python
.. literalinclude:: helloworld.py
   :linenos:
   from pyramid.config import Configurator
   from pyramid.response import Response
   from paste.httpserver import serve
   :lines: 1-2
The script imports the :class:`~pyramid.config.Configurator` class from the
:mod:`pyramid.config` module.  An instance of the
:class:`~pyramid.config.Configurator` class is later used to configure your
:app:`Pyramid` application.
The script uses the :class:`pyramid.response.Response` class later in the
script to create a :term:`response` object.
Like many other Python web frameworks, :app:`Pyramid` uses the :term:`WSGI`
protocol to connect an application and a web server together.  The
@@ -85,25 +62,18 @@
View Callable Declarations
~~~~~~~~~~~~~~~~~~~~~~~~~~
The above script, beneath its set of imports, defines two functions: one
named ``hello_world`` and one named ``goodbye_world``.
The above script, beneath its set of imports, defines a function
named ``hello_world``.
.. code-block:: python
.. literalinclude:: helloworld.py
   :linenos:
   :pyobject: hello_world
   def hello_world(request):
       return Response('Hello world!')
This function doesn't do anything very difficult.  The functions accepts a
single argument (``request``).  The ``hello_world`` function returns a value
computed from arguments matched from the url route.
   def goodbye_world(request):
       return Response('Goodbye world!')
These functions don't do anything very difficult.  Both functions accept a
single argument (``request``).  The ``hello_world`` function does nothing but
return a response instance with the body ``Hello world!``.  The
``goodbye_world`` function returns a response instance with the body
``Goodbye world!``.
Each of these functions is known as a :term:`view callable`.  A view callable
This function is known as a :term:`view callable`.  A view callable
accepts a single argument, ``request``.  It is expected to return a
:term:`response` object.  A view callable doesn't need to be a function; it
can be represented via another type of object, like a class or an instance,
@@ -118,9 +88,7 @@
response; this object is then converted to text by the upstream :term:`WSGI`
server and sent back to the requesting browser.  To return a response, each
view callable creates an instance of the :class:`~pyramid.response.Response`
class.  In the ``hello_world`` function, the string ``'Hello world!'`` is
passed to the ``Response`` constructor as the *body* of the response.  In the
``goodbye_world`` function, the string ``'Goodbye world!'`` is passed.
class.  In the ``hello_world`` function, the string is passed.
.. note:: As we'll see in later chapters, returning a literal
   :term:`response` object from a view callable is not always required; we
@@ -143,26 +111,18 @@
defined imports and function definitions, placed within the confines of an
``if`` statement:
.. code-block:: python
.. literalinclude:: helloworld.py
   :linenos:
   if __name__ == '__main__':
       config = Configurator()
       config.add_view(hello_world)
       config.add_view(goodbye_world, name='goodbye')
       app = config.make_wsgi_app()
       serve(app, host='0.0.0.0')
   :lines: 7-12
Let's break this down piece-by-piece.
Configurator Construction
~~~~~~~~~~~~~~~~~~~~~~~~~
.. code-block:: python
.. literalinclude:: helloworld.py
   :linenos:
   if __name__ == '__main__':
       config = Configurator()
   :lines: 7-8
The ``if __name__ == '__main__':`` line in the code sample above represents a
Python idiom: the code inside this if clause is not invoked unless the script
@@ -193,44 +153,32 @@
~~~~~~~~~~~~~~~~~~~~
.. ignore-next-block
.. code-block:: python
.. literalinclude:: helloworld.py
   :linenos:
   :lines: 9-10
   config.add_view(hello_world)
   config.add_view(goodbye_world, name='goodbye')
Each of these lines calls the :meth:`pyramid.config.Configurator.add_view`
method.  The ``add_view`` method of a configurator registers a :term:`view
configuration` within the :term:`application registry`.  A :term:`view
configuration` represents a set of circumstances related to the
First line is to call the :meth:`pyramid.config.Configurator.add_route`
which registers a :term:`route` to match any url with ``/hello/`` followed
by a string. The :meth:`pyramid.config.Configurator.add_view` method of
a configurator registers a :term:`view configuration` within the
:term:`application registry`.  A :term:`view configuration` and
:term:`route configuration` represents a set of circumstances related to the
:term:`request` that will cause a specific :term:`view callable` to be
invoked.  This "set of circumstances" is provided as one or more keyword
arguments to the ``add_view`` method.  Each of these keyword arguments is
known as a view configuration :term:`predicate`.
The line ``config.add_view(hello_world)`` registers the ``hello_world``
function as a view callable.  The ``add_view`` method of a Configurator must
be called with a view callable object or a :term:`dotted Python name` as its
The line ``config.add_view(hello_world, route_name='hello')`` registers the
``hello_world`` function as a view callable.  The ``add_view`` method
of a Configurator must be called with a view callable object or a
:term:`dotted Python name` as its
first argument, so the first argument passed is the ``hello_world`` function.
This line calls ``add_view`` with a *default* value for the :term:`predicate`
argument, named ``name``.  The ``name`` predicate defaults to a value
equalling the empty string (``''``).  This means that we're instructing
:app:`Pyramid` to invoke the ``hello_world`` view callable when the
:term:`view name` is the empty string.  We'll learn in later chapters what a
:term:`view name` is, and under which circumstances a request will have a
view name that is the empty string; in this particular application, it means
that the ``hello_world`` view callable will be invoked when the root URL
``/`` is visited by a browser.
The line ``config.add_view(goodbye_world, name='goodbye')`` registers the
``goodbye_world`` function as a view callable.  The line calls ``add_view``
with the view callable as the first required positional argument, and a
:term:`predicate` keyword argument ``name`` with the value ``'goodbye'``.
The ``name`` argument supplied in this :term:`view configuration` implies
that only a request that has a :term:`view name` of ``goodbye`` should cause
the ``goodbye_world`` view callable to be invoked.  In this particular
application, this means that the ``goodbye_world`` view callable will be
invoked when the URL ``/goodbye`` is visited by a browser.
This line calls ``add_view`` with a ``route_name`` ``predicate`` value of
``hello``.  This means that we're instructing
:app:`Pyramid` to invoke the ``hello_world`` view callable if the
:term:`route` is matched is ``hello``.  In :app:`Pyramid` the use of a
:term:`route` is only one of ways you can link a url to a :term:`view callable`
and is called :term:`URL Dispatch`.
Each invocation of the ``add_view`` method registers a :term:`view
configuration`.  Each :term:`predicate` provided as a keyword argument to the
@@ -240,14 +188,8 @@
the applicability of its associated view callable.  When :app:`Pyramid`
processes a request, the view callable with the *most specific* view
configuration (the view configuration that matches the most specific set of
predicates) is always invoked.
In this application, :app:`Pyramid` chooses the most specific view callable
based only on view :term:`predicate` applicability.  The ordering of calls to
:meth:`~pyramid.config.Configurator.add_view` is never very important.  We can
register ``goodbye_world`` first and ``hello_world`` second; :app:`Pyramid`
will still give us the most specific callable when a request is dispatched to
it.
predicates) is always invoked. In this application, :app:`Pyramid` chooses the most specific view callable
based only on view :term:`predicate` applicability.
.. index::
   single: make_wsgi_app
@@ -257,10 +199,9 @@
~~~~~~~~~~~~~~~~~~~~~~~~~
.. ignore-next-block
.. code-block:: python
.. literalinclude:: helloworld.py
   :linenos:
   app = config.make_wsgi_app()
   :lines: 11
After configuring views and ending configuration, the script creates a WSGI
*application* via the :meth:`pyramid.config.Configurator.make_wsgi_app`
@@ -280,17 +221,16 @@
configurator used to configure it.  The :term:`router` consults the registry
to obey the policy choices made by a single application.  These policy
choices were informed by method calls to the :term:`Configurator` made
earlier; in our case, the only policy choices made were implied by two calls
to its ``add_view`` method.
earlier; in our case, the only policy choices made were implied by calls
to its ``add_view`` and ``add_route`` methods.
WSGI Application Serving
~~~~~~~~~~~~~~~~~~~~~~~~
.. ignore-next-block
.. code-block:: python
.. literalinclude:: helloworld.py
   :linenos:
   serve(app, host='0.0.0.0')
   :lines: 12
Finally, we actually serve the application to requestors by starting up a
WSGI server.  We happen to use the :func:`paste.httpserver.serve` WSGI server
docs/narr/helloworld.py
New file
@@ -0,0 +1,12 @@
from paste.httpserver import serve
from pyramid.configuration import Configurator
def hello_world(request):
   return 'Hello %(name)s!' % request.matchdict
if __name__ == '__main__':
   config = Configurator()
   config.add_route('hello', '/hello/{name}')
   config.add_view(hello_world, route_name='hello')
   app = config.make_wsgi_app()
   serve(app, host='0.0.0.0')