PageRenderTime 28ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/docs/narr/firstapp.rst

https://github.com/archanmishra/pyramid
ReStructuredText | 239 lines | 182 code | 57 blank | 0 comment | 0 complexity | 23f4824bc1e03e75587f6d3eb6bd8a68 MD5 | raw file
  1. .. index::
  2. single: hello world program
  3. .. _firstapp_chapter:
  4. Creating Your First :app:`Pyramid` Application
  5. =================================================
  6. In this chapter, we will walk through the creation of a tiny :app:`Pyramid`
  7. application. After we're finished creating the application, we'll explain in
  8. more detail how it works.
  9. .. _helloworld_imperative:
  10. Hello World
  11. -----------
  12. Here's one of the very simplest :app:`Pyramid` applications:
  13. .. literalinclude:: helloworld.py
  14. :linenos:
  15. When this code is inserted into a Python script named ``helloworld.py`` and
  16. executed by a Python interpreter which has the :app:`Pyramid` software
  17. installed, an HTTP server is started on TCP port 8080:
  18. .. code-block:: text
  19. $ python helloworld.py
  20. serving on 0.0.0.0:8080 view at http://127.0.0.1:8080
  21. When port 8080 is visited by a browser on the URL ``/hello/world``, the
  22. server will simply serve up the text "Hello world!"
  23. Press ``Ctrl-C`` to stop the application.
  24. Now that we have a rudimentary understanding of what the application does,
  25. let's examine it piece-by-piece.
  26. Imports
  27. ~~~~~~~
  28. The above ``helloworld.py`` script uses the following set of import
  29. statements:
  30. .. literalinclude:: helloworld.py
  31. :linenos:
  32. :lines: 1-3
  33. The script imports the :class:`~pyramid.config.Configurator` class from the
  34. :mod:`pyramid.config` module. An instance of the
  35. :class:`~pyramid.config.Configurator` class is later used to configure your
  36. :app:`Pyramid` application.
  37. Like many other Python web frameworks, :app:`Pyramid` uses the :term:`WSGI`
  38. protocol to connect an application and a web server together. The
  39. :mod:`paste.httpserver` server is used in this example as a WSGI server for
  40. convenience, as the ``paste`` package is a dependency of :app:`Pyramid`
  41. itself.
  42. The script also imports the :class:`pyramid.response.Response` class for
  43. later use. An instance of this class will be used to create a web response.
  44. View Callable Declarations
  45. ~~~~~~~~~~~~~~~~~~~~~~~~~~
  46. The above script, beneath its set of imports, defines a function
  47. named ``hello_world``.
  48. .. literalinclude:: helloworld.py
  49. :linenos:
  50. :pyobject: hello_world
  51. This function doesn't do anything very difficult. The functions accepts a
  52. single argument (``request``). The ``hello_world`` function returns an
  53. instance of the :class:`pyramid.response.Response`. The single argument to
  54. the class' constructor is value computed from arguments matched from the url
  55. route. This value becomes the body of the response.
  56. This function is known as a :term:`view callable`. A view callable
  57. accepts a single argument, ``request``. It is expected to return a
  58. :term:`response` object. A view callable doesn't need to be a function; it
  59. can be represented via another type of object, like a class or an instance,
  60. but for our purposes here, a function serves us well.
  61. A view callable is always called with a :term:`request` object. A request
  62. object is a representation of an HTTP request sent to :app:`Pyramid` via the
  63. active :term:`WSGI` server.
  64. A view callable is required to return a :term:`response` object because a
  65. response object has all the information necessary to formulate an actual HTTP
  66. response; this object is then converted to text by the :term:`WSGI` server
  67. which called Pyramid and it is sent back to the requesting browser. To
  68. return a response, each view callable creates an instance of the
  69. :class:`~pyramid.response.Response` class. In the ``hello_world`` function,
  70. a string is passed as the body to the response.
  71. .. index::
  72. single: imperative configuration
  73. single: Configurator
  74. single: helloworld (imperative)
  75. .. _helloworld_imperative_appconfig:
  76. Application Configuration
  77. ~~~~~~~~~~~~~~~~~~~~~~~~~
  78. In the above script, the following code represents the *configuration* of
  79. this simple application. The application is configured using the previously
  80. defined imports and function definitions, placed within the confines of an
  81. ``if`` statement:
  82. .. literalinclude:: helloworld.py
  83. :linenos:
  84. :lines: 8-13
  85. Let's break this down piece-by-piece.
  86. Configurator Construction
  87. ~~~~~~~~~~~~~~~~~~~~~~~~~
  88. .. literalinclude:: helloworld.py
  89. :linenos:
  90. :lines: 8-9
  91. The ``if __name__ == '__main__':`` line in the code sample above represents a
  92. Python idiom: the code inside this if clause is not invoked unless the script
  93. containing this code is run directly from the operating system command
  94. line. For example, if the file named ``helloworld.py`` contains the entire
  95. script body, the code within the ``if`` statement will only be invoked when
  96. ``python helloworld.py`` is executed from the command line.
  97. Using the ``if`` clause is necessary -- or at least best practice -- because
  98. code in a Python ``.py`` file may be eventually imported via the Python
  99. ``import`` statement by another ``.py`` file. ``.py`` files that are
  100. imported by other ``.py`` files are referred to as *modules*. By using the
  101. ``if __name__ == 'main':`` idiom, the script above is indicating that it does
  102. not want the code within the ``if`` statement to execute if this module is
  103. imported from another; the code within the ``if`` block should only be run
  104. during a direct script execution.
  105. The ``config = Configurator()`` line above creates an instance of the
  106. :class:`~pyramid.config.Configurator` class. The resulting ``config`` object
  107. represents an API which the script uses to configure this particular
  108. :app:`Pyramid` application. Methods called on the Configurator will cause
  109. registrations to be made in an :term:`application registry` associated with
  110. the application.
  111. .. _adding_configuration:
  112. Adding Configuration
  113. ~~~~~~~~~~~~~~~~~~~~
  114. .. ignore-next-block
  115. .. literalinclude:: helloworld.py
  116. :linenos:
  117. :lines: 10-11
  118. First line above calls the :meth:`pyramid.config.Configurator.add_route`
  119. method, which registers a :term:`route` to match any url path that begins
  120. with ``/hello/`` followed by a string.
  121. The second line, ``config.add_view(hello_world, route_name='hello')``,
  122. registers the ``hello_world`` function as a :term:`view callable` and makes
  123. sure that it will be called when the ``hello`` route is matched.
  124. .. index::
  125. single: make_wsgi_app
  126. single: WSGI application
  127. WSGI Application Creation
  128. ~~~~~~~~~~~~~~~~~~~~~~~~~
  129. .. ignore-next-block
  130. .. literalinclude:: helloworld.py
  131. :linenos:
  132. :lines: 12
  133. After configuring views and ending configuration, the script creates a WSGI
  134. *application* via the :meth:`pyramid.config.Configurator.make_wsgi_app`
  135. method. A call to ``make_wsgi_app`` implies that all configuration is
  136. finished (meaning all method calls to the configurator which set up views,
  137. and various other configuration settings have been performed). The
  138. ``make_wsgi_app`` method returns a :term:`WSGI` application object that can
  139. be used by any WSGI server to present an application to a requestor.
  140. :term:`WSGI` is a protocol that allows servers to talk to Python
  141. applications. We don't discuss :term:`WSGI` in any depth within this book,
  142. however, you can learn more about it by visiting `wsgi.org
  143. <http://wsgi.org>`_.
  144. The :app:`Pyramid` application object, in particular, is an instance of a
  145. class representing a :app:`Pyramid` :term:`router`. It has a reference to
  146. the :term:`application registry` which resulted from method calls to the
  147. configurator used to configure it. The :term:`router` consults the registry
  148. to obey the policy choices made by a single application. These policy
  149. choices were informed by method calls to the :term:`Configurator` made
  150. earlier; in our case, the only policy choices made were implied by calls
  151. to its ``add_view`` and ``add_route`` methods.
  152. WSGI Application Serving
  153. ~~~~~~~~~~~~~~~~~~~~~~~~
  154. .. ignore-next-block
  155. .. literalinclude:: helloworld.py
  156. :linenos:
  157. :lines: 13
  158. Finally, we actually serve the application to requestors by starting up a
  159. WSGI server. We happen to use the :func:`paste.httpserver.serve` WSGI server
  160. runner, passing it the ``app`` object (a :term:`router`) as the application
  161. we wish to serve. We also pass in an argument ``host=='0.0.0.0'``, meaning
  162. "listen on all TCP interfaces." By default, the Paste HTTP server listens
  163. only on the ``127.0.0.1`` interface, which is problematic if you're running
  164. the server on a remote system and you wish to access it with a web browser
  165. from a local system. We don't specify a TCP port number to listen on; this
  166. means we want to use the default TCP port, which is 8080.
  167. When this line is invoked, it causes the server to start listening on TCP
  168. port 8080. The server will serve requests forever, or at least until we stop
  169. it by killing the process which runs it (usually by pressing ``Ctrl-C`` in
  170. the terminal we used to start it).
  171. Conclusion
  172. ~~~~~~~~~~
  173. Our hello world application is one of the simplest possible :app:`Pyramid`
  174. applications, configured "imperatively". We can see that it's configured
  175. imperatively because the full power of Python is available to us as we
  176. perform configuration tasks.
  177. References
  178. ----------
  179. For more information about the API of a :term:`Configurator` object,
  180. see :class:`~pyramid.config.Configurator` .
  181. For more information about :term:`view configuration`, see
  182. :ref:`view_config_chapter`.