diff options
Diffstat (limited to 'docs/getting_started/quick_glance.rst')
| -rw-r--r-- | docs/getting_started/quick_glance.rst | 539 |
1 files changed, 0 insertions, 539 deletions
diff --git a/docs/getting_started/quick_glance.rst b/docs/getting_started/quick_glance.rst deleted file mode 100644 index 13ae22ba5..000000000 --- a/docs/getting_started/quick_glance.rst +++ /dev/null @@ -1,539 +0,0 @@ -============ -Quick Glance -============ - -Pyramid lets you start small and finish big. The -:doc:`index` guide -walks you through many of the key features. Let's put the emphasis on -*start* by doing a quick tour through Pyramid. - -This *Quick Glance* is shorthand, snippet-oriented. It is not intended -as full example. Instead, the other chapters will provide complete -examples. - -.. note:: - - Like the rest of Getting Started, we're using Python 3 in - our samples. You can too, or you can use Python 2.7. - -The Smallest -============ - -Microframeworks have shown that learning starts best from a very small -first step. Here's a tiny application in Pyramid: - -.. literalinclude:: quick_glance/app1.py - -This simple example is easy to run. Save this as ``app.py`` and run it: - -.. code-block:: bash - - $ python3 ./app.py - -Finally, open `http://localhost:8081/ <http://localhost:8081/>`_ in a -browser and you will see the ``Hello World!`` message. - -At a high level, we wrote a Python module, which when executed, -started an HTTP server. This HTTP server ran a WSGI application with -one "view". This view handled the ``http://localhost:8081/`` URL. - -More specifically: - -#. We imported an HTTP server (``make_server``), a configuration system - (``Configurator``), and a way to send HTTP responses (``Response``). - -#. We made a ``hello_world`` function that returned a ``Response``. - -#. Our ``main`` function started the configuration, added a "route", - and then mapped that route to a "view". - -#. To finish, we then made a WSGI app and served it. - ``if __name__ == '__main__':`` is a standard Python technique to - execute code when it is run from the command line instead of - imported into another module. - -.. note:: - - The configuration of the route and the view are split. Other systems - let you bundle those together. Pyramid makes you do the extra step, - but for a reason: this lets you control the ordering. More on this - later. - -Using Decorators and Matchdicts -=============================== - -Let's repeat the smallest step, but make it a little more functional -and elegant by adding: - -- Echo back a name sent in via the URL - -- The URL is below the top of the site - -- Use a decorator to register the view - -Let's make update our ``app.py`` module: - -.. literalinclude:: quick_glance/app2.py - :linenos: - -When you run ``python3 ./app.py`` and visit a URL such as -``http://localhost:8081/hello/amy``, the response includes ``amy`` in -the HTML. - -This module, while small, starts to show how many Pyramid applications -are composed: - -#. We use a decorator around the view, to put the configuration closer - to the code. - -#. We tell the ``Configurator`` to go look for decorators. - -Templates -========= - -You usually won't embed an HTML string directly in Python, but instead, -will use a templating language. Pyramid comes bundled with Chameleon -and Mako, but Jinja2 is popular. Let's install it: - -.. code-block:: bash - - $ pip install pyramid_jinja2 - -With the package installed, we can include the template bindings into -our configuration: - -.. code-block:: python - - config.include('pyramid_jinja2') - -Our view changes. We only return Python data and let the ``renderer`` -argument tell Pyramid to pass the response through Jinja2: - -.. code-block:: python - - @view_config(route_name='hello', renderer="app3.jinja2") - def hello_world(request): - return dict(name=request.matchdict['name']) - -Our template is HTML-oriented with a little logic in the ``<h1>``: - -.. code-block:: html - - <html lang="en"> - <html xmlns="http://www.w3.org/1999/xhtml"> - <head> - <title>Quick Glance</title> - </head> - <body> - <h1>Hello {{ name }}!</h1> - </body> - </html> - -Static Assets -============= - -Of course the Web is more than just markup. You need static assets: -CSS, JS, and images. Let's point our web app at a directory where -Pyramid will serve some static assets. First, another call to the -``Configurator``: - -.. code-block:: python - - config.add_static_view(name='static', path='static') - -This tells our WSGI application to map requests under -``http://localhost:8081/static/`` to files and directories inside a -``static`` directory alongside our Python module. - -Next, make a directory ``static`` and place ``app.css`` inside: - -.. code-block:: css - - body { - margin: 2em; - font-family: sans-serif; - } - -All we need to do now is point to it in the ``<head>`` of our Jinja2 -template: - -.. code-block:: html - - <link rel="stylesheet" href="/static/app.css" /> - -Returning JSON -============== - -Modern web apps are more than rendered HTML. Dynamic pages now use -JavaScript update the UI in the browser by requesting server data as -JSON. - -Pyramid supports this with a JSON renderer: - -.. code-block:: python - - @view_config(route_name='hello_json', renderer='json') - def hello_json(request): - return [1, 2, 3] - -This wires up a view that returns some data through the JSON -"renderer", which calls Python's JSON support to serialize the data -into JSON, set the appropriate HTTP headers, and more. - -The view needs a route added to the ``Configurator``: - -.. code-block:: python - - config.add_route('hello_json', 'hello.json') - - -View Classes -============ - -Free-standing functions are the regular way to do views. Many times, -though, you have several views that are closely related. For example, -a document might have many different ways to look at it. - -For some people, grouping these together makes logical sense. A view -class lets you group views, sharing some state assignments, and -using helper functions as class methods. - -Let's re-organize our two views into methods on a view class: - -.. code-block:: python - - class HelloWorldViews: - def __init__(self, request): - self.request = request - - @view_config(route_name='hello', renderer='app4.jinja2') - def hello_world(self): - return dict(name=self.request.matchdict['name']) - - - @view_config(route_name='hello_json', renderer='json') - def hello_json(self): - return [1, 2, 3] - -Everything else remains the same. - -Quick Project Startup with Scaffolds -==================================== - -So far we have done all of our *Quick Glance* as a single Python file. -No Python packages, no structure. Most Pyramid projects, though, -aren't developed this way. - -To ease the process of getting started, Pyramid provides *scaffolds* -that generate sample projects. Not just Pyramid itself: add-ons such as -``pyramid_jinja2`` (or your own projects) can register there own -scaffolds. - -We use Pyramid's ``pcreate`` command to generate our starting point -from a scaffold. What does this command look like? - -.. code-block:: bash - - $ pcreate --help - Usage: pcreate [options] output_directory - - Render Pyramid scaffolding to an output directory - - Options: - -h, --help show this help message and exit - -s SCAFFOLD_NAME, --scaffold=SCAFFOLD_NAME - Add a scaffold to the create process (multiple -s args - accepted) - -t SCAFFOLD_NAME, --template=SCAFFOLD_NAME - A backwards compatibility alias for -s/--scaffold. - Add a scaffold to the create process (multiple -t args - accepted) - -l, --list List all available scaffold names - --list-templates A backwards compatibility alias for -l/--list. List - all available scaffold names. - --simulate Simulate but do no work - --overwrite Always overwrite - --interactive When a file would be overwritten, interrogate - -Let's see what our Pyramid install supports as starting-point scaffolds: - -.. code-block:: bash - - $ pcreate --list - Available scaffolds: - alchemy: Pyramid SQLAlchemy project using url dispatch - pyramid_jinja2_starter: pyramid jinja2 starter project - starter: Pyramid starter project - zodb: Pyramid ZODB project using traversal - -The ``pyramid_jinja2_starter`` looks interesting. From the parent -directory of where we want our Python package to be generated, -let's use that scaffold to make our project: - -.. code-block:: bash - - $ pcreate --scaffold pyramid_jinja2_starter hello_world - -After printing a bunch of lines about the files being generated, -we now have a Python package. As described in the *official -instructions*, we need to install this as a development package: - -.. code-block:: bash - - $ cd hello_world - $ python3.3 ./setup.py develop - -What did we get? A top-level directory ``hello_world`` that includes -some packaging files and a subdirectory ``hello_world`` that has -sample files for our application: - -.. code-block:: bash - - $ ls - CHANGES.txt development.ini hello_world.egg-info - MANIFEST.in message-extraction.ini setup.cfg - README.txt hello_world setup.py - - $ ls hello_world - __init__.py locale static tests.py - __pycache__ models.py templates views.py - -We are moving in the direction of a full-featured Pyramid project, -with a proper setup for Python standards (packaging) and Pyramid -configuration. This includes a new way of running your application: - -.. code-block:: bash - - $ pserve development.ini - -With ``pserve``, your application isn't responsible for finding a WSGI -server and launching your WSGI app. Also, much of the wiring of your -application can be moved to a declarative ``.ini`` configuration file. - -In your browser, visit -`http://localhost:6543/ <http://localhost:6543/>`_ and you'll see that -things look very different. In the next few sections we'll cover some -decisions made by this scaffold. - -Let's look at ``pserve`` and configuration in more depth. - -Application Running with ``pserve`` -=================================== - -When you install Pyramid, a small command program called ``pserve`` is -written to your ``bin`` directory. This program is an executable Python -module. It's very small, getting most of its brains via import. - -You can run ``pserve`` with ``--help`` to see some of its options. -Doing so reveals that you can ask ``pserve`` to watch your development -files and reload the server when they change: - -.. code-block:: bash - - $ pserve development.ini --reload - -By design, ``pserve`` itself isn't all that interesting. Instead, -its brains from your project's wiring, as expressed in the -configuration file you supply it. - -.. seealso:: See Also: :ref:`what_is_this_pserve_thing` - -Three Cool Things About ``pserve`` ----------------------------------- - -1. *Multiple .ini files*. You might have some settings in - development mode or some in production mode. Maybe you are writing an - add-on that needs to be wired-up by other people. - -2. *Choice of WSGI server*. ``pserve`` itself isn't a WSGI server. - Instead, it loads the server you want from the configuration file. - -3. *Friends of pserve*. With the ``pserve``/``.ini`` approach you - also get other commands that help during development: ``pshell``, - ``proutes``, ``pviews``, ``prequest``, etc. - -Configuration with ``.ini`` Files -================================= - -Earlier in *Quick Glance* we first met Pyramid's configuration system. -At that point we did all configuration in Python code, -aka *imperatively*. For example, the port number chosen for our HTTP -server was right there in Python code. Our scaffold has moved this -decision, and more, into *declarative* configuration in the -``development.ini`` file. - -Let's take a quick high-level look. First, the ``.ini`` file is divided -into sections: - -- ``[app:hello_world]`` configures our WSGI app - -- ``[pipeline:main]`` sets up our WSGI "pipeline" - -- ``[server:main]`` holds our WSGI server settings - -- Various sections afterwards configure our Python logging system - -Let's look at a few decisions made in this configuration: - -#. *Choice of web server*. The ``use = egg:pyramid#wsgiref`` tell - ``pserve`` to the ``wsgiref`` server that is wrapped in the Pyramid - package. - -#. *Port number*. ``port = 6543`` tells ``wsgiref`` to listen on port - 6543. - -#. *WSGI app*. What package has our WSGI application in it? - ``use = egg:hello_world`` in the app section tells the - configuration what application to load. - -#. *Easier development by automatic template reloading*. In development - mode, you shouldn't have to restart the server when editing a Jinja2 - template. ``reload_templates = true`` sets this policy, - which might be different in production. - -Additionally, the ``development.ini`` generated by this scaffold wired -up Python's standard logging. We'll now see in the console, for example, -a log on every request that comes in, as well traceback information. - -Easier Development with ``debugtoolbar`` -======================================== - -As we introduce the basics we also want to show how to be productive in -development and debugging. For example, we just discussed template -reloading and earlier we showed ``--reload`` for application reloading. - -``pyramid_debugtoolbar`` is a popular Pyramid add-on which makes -several tools available in your browser. Adding it to your project -illustrates several points about configuration. - -First, change your ``setup.py`` to say: - -.. code-block:: python - - requires=['pyramid>=1.0.2', 'pyramid_jinja2'] - -...and re-run your setup: - -.. code-block:: bash - - $ python3.3 ./setup.py develop - -The Python package was now installed into our environment but we -haven't told our web app to use it. We can do so imperatively in code: - -.. code-block:: python - - config.include('pyramid_debugtoolbar') - -Instead, let's do it in configuration by modifying our -``development.ini`` instead: - -.. code-block:: ini - - [app:hello_world] - pyramid.includes = pyramid_debugtoolbar - -That is, add ``pyramid.includes = pyramid_debugtoolbar`` anywhere in the -``[app:hello_world]`` section. You'll now see an attractive (and -collapsible) menu in the right of your browser giving you introspective -access to debugging information. Even better, if your web application -generates an error, you will see a nice traceback on the screen. - -Unit Tests and ``nose`` -======================= - -Yikes! We got this far and we haven't yet discussed tests. Particularly -egregious, as Pyramid has had a deep commitment to full test coverage -since before it was released. - -Our ``pyramid_jinja2_starter`` scaffold generated a ``tests.py`` module -with one unit test in it. To run it, let's install the handy ``nose`` -test runner by editing ``setup.py``. While we're at it, we'll throw in -the ``coverage`` tool which yells at us for code that isn't tested: - -.. code-block:: python - - setup(name='hello_world', - # Some lines removed... - extras_require={ - 'testing': ['nose', 'coverage'], - } - ) - -We changed ``setup.py`` which means we need to re-run -``python3.3 ./setup.py develop``. We can now run all our tests: - -.. code-block:: bash - - $ nosetests - . - Name Stmts Miss Cover Missing - --------------------------------------------------- - hello_world 12 8 33% 11-23 - hello_world.models 5 1 80% 8 - hello_world.tests 14 0 100% - hello_world.views 4 0 100% - --------------------------------------------------- - TOTAL 35 9 74% - ---------------------------------------------------------------------- - Ran 1 test in 0.931s - - OK - -Our unit test passed. What did our test look like? - -.. code-block:: python - - import unittest - from pyramid import testing - - - class ViewTests(unittest.TestCase): - def setUp(self): - testing.setUp() - - def tearDown(self): - testing.tearDown() - - def test_my_view(self): - from hello_world.views import my_view - - request = testing.DummyRequest() - response = my_view(request) - self.assertEqual(response['project'], 'hello_world') - -Pyramid supplies helpers for test writing, which we use in the -test setup and teardown. Our one test imports the view, -makes a dummy request, and sees if the view returns what we expected. - - - - - logging - - - resources, asset specs, tests, - -sessions, logging, special views -databases, forms, security - -Notes - -- Change 8081 -> 6543 - -- See also, interlinking, teasers or "3 Extras" at the end of each - section, links to a downloadable version of the Python module - -- Read "pyramid for humans" and getting started as an attempt to kill - those - -- Do a better job at the "why" - -- Explain imperative vs. declarative configuration and link to "why - configuration" - -- For see also, point also to Getting Started sections - -- Debugging - -- Template reloading - -- Explain and link to WSGI, Python Packages
\ No newline at end of file |
