summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorPaul Everitt <paul@agendaless.com>2013-08-07 15:34:58 -0400
committerPaul Everitt <paul@agendaless.com>2013-08-07 15:34:58 -0400
commit65d1719fc5ce4ed4e87c45b1e4279c30930b274e (patch)
treef874999cd13ab9637682d5c79945818b393155e7 /docs
parent30c51bd60756ab632553319a231e154c582b8cd1 (diff)
downloadpyramid-65d1719fc5ce4ed4e87c45b1e4279c30930b274e.tar.gz
pyramid-65d1719fc5ce4ed4e87c45b1e4279c30930b274e.tar.bz2
pyramid-65d1719fc5ce4ed4e87c45b1e4279c30930b274e.zip
Up through scaffolds.
Diffstat (limited to 'docs')
-rw-r--r--docs/getting_started/quick_glance.rst139
-rw-r--r--docs/getting_started/quick_glance/jinja2/hello_world.jinja22
-rw-r--r--docs/getting_started/quick_glance/json/hello_world.jinja24
-rw-r--r--docs/getting_started/quick_glance/json/hello_world.pt2
-rw-r--r--docs/getting_started/quick_glance/static_assets/hello_world.jinja24
-rw-r--r--docs/getting_started/quick_glance/static_assets/hello_world.pt5
-rw-r--r--docs/getting_started/quick_glance/templating/hello_world.pt1
-rw-r--r--docs/getting_started/quick_glance/view_classes/app.py23
-rw-r--r--docs/getting_started/quick_glance/view_classes/delete.jinja29
-rw-r--r--docs/getting_started/quick_glance/view_classes/edit.jinja29
-rw-r--r--docs/getting_started/quick_glance/view_classes/hello.jinja217
-rw-r--r--docs/getting_started/quick_glance/view_classes/views.py32
-rw-r--r--docs/getting_started/scaffolds.rst100
-rw-r--r--docs/getting_started/views.rst37
14 files changed, 259 insertions, 125 deletions
diff --git a/docs/getting_started/quick_glance.rst b/docs/getting_started/quick_glance.rst
index b04baeec8..7189a0d13 100644
--- a/docs/getting_started/quick_glance.rst
+++ b/docs/getting_started/quick_glance.rst
@@ -19,8 +19,8 @@ Python Setup
First things first: we need our Python environment in ship-shape.
Pyramid encourages standard Python development practices (virtual
-environments, packaging tools, etc.) so let's get our working area in
-place. For Python 3.3:
+environments, packaging tools, logging, etc.) so let's get our working
+area in place. For Python 3.3:
.. code-block:: bash
@@ -151,6 +151,14 @@ view. The ``hello_view`` (available at the URL ``/howdy``) has a link
to the ``redirect_view``, which shows issuing a redirect to the final
view.
+Earlier we saw ``config.add_view`` as one way to configure a view. This
+section introduces ``@view_config``. Pyramid's configuration supports
+:term:`imperative configuration`, such as the ``config.add_view`` in
+the previous example. You can also use :term:`declarative
+configuration`, in which a Python :term:`decorator` is placed on the
+line above the view. Both approaches result in the same final
+configuration, thus usually, it is simply a matter of taste.
+
.. note::
We're focusing on one topic at a time, thus we are leaving out
@@ -337,50 +345,43 @@ into JSON and set the appropriate HTTP headers.
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
+So far our views have been simple, free-standing functions. Many times
+your views are related: different ways to look at or work on the same
+data or a REST API that handles multiple operations. Grouping these
+together as a
+:ref:`view class <class_as_view>` makes sense:
- @view_config(route_name='hello', renderer='app4.jinja2')
- def hello_world(self):
- return dict(name=self.request.matchdict['name'])
+- Group views
+- Centralize some repetitive defaults
- @view_config(route_name='hello_json', renderer='json')
- def hello_json(self):
- return [1, 2, 3]
+- Share some state and helpers
-Everything else remains the same.
+The following shows a "Hello World" example with three operations: view
+a form, save a change, or press the delete button:
+.. literalinclude:: quick_glance/view_classes/views.py
+ :start-after: Start View 1
+ :end-before: End View 1
-Configuration
-=============
-
+As you can see, the three views are logically grouped together.
+Specifically:
-#. *Line 7*. Pyramid's configuration supports
- :term:`imperative configuration`, such as the ``config.add_view`` in
- the previous example. You can also use
- :term:`declarative configuration`, in which a Python
- :term:`decorator` is placed on the line above the view.
+- The first view is returned when you go to ``/howdy/amy``. This URL is
+ mapped to the ``hello`` route that we centrally set using the optional
+ ``@view_defaults``.
-#. *Line 15*. Tell the configurator to go look for decorators.
+- The second view is returned when the form data contains a field with
+ ``form.edit``, such as clicking on
+ ``<input type="submit" name="form.edit" value="Save"/>``. This rule
+ is specified in the ``@view_config`` for that view.
-- Move route declarations into views, with prefix thingy
+- The third view is returned when clicking on a button such
+ as ``<input type="submit" name="form.delete" value="Delete"/>``.
-Packages
-========
+Only one route needed, stated in one place atop the view class. Also,
+the assignment of the ``name`` is done in the ``__init__``. Our
+templates can then use ``{{ view.name }}``.
Quick Project Startup with Scaffolds
====================================
@@ -390,37 +391,8 @@ 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:
+that generate sample projects from templates in Pyramid and Pyramid
+add-ons. Pyramid's ``pcreate`` command can list the available scaffolds:
.. code-block:: bash
@@ -431,38 +403,22 @@ Let's see what our Pyramid install supports as starting-point scaffolds:
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,
+The ``pyramid_jinja2`` add-on gave us a scaffold that we can use. 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:
+We next use the normal Python development to setup our package for
+development:
.. code-block:: bash
$ cd hello_world
$ python ./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:
@@ -471,15 +427,6 @@ configuration. This includes a new way of running your application:
$ 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``
diff --git a/docs/getting_started/quick_glance/jinja2/hello_world.jinja2 b/docs/getting_started/quick_glance/jinja2/hello_world.jinja2
index 5fc1fc9bf..e177744b5 100644
--- a/docs/getting_started/quick_glance/jinja2/hello_world.jinja2
+++ b/docs/getting_started/quick_glance/jinja2/hello_world.jinja2
@@ -1,6 +1,6 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
- <title>Quick Glance</title>
+ <title>Hello World</title>
</head>
<body>
<h1>Hello {{ name }}!</h1>
diff --git a/docs/getting_started/quick_glance/json/hello_world.jinja2 b/docs/getting_started/quick_glance/json/hello_world.jinja2
index 3d0f28c1f..f6862e618 100644
--- a/docs/getting_started/quick_glance/json/hello_world.jinja2
+++ b/docs/getting_started/quick_glance/json/hello_world.jinja2
@@ -1,8 +1,8 @@
+<!DOCTYPE html>
<html lang="en">
-<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Quick Glance</title>
- <link rel="stylesheet" href="/static/app.css" />
+ <link rel="stylesheet" href="/static/app.css"/>
</head>
<body>
<h1>Hello {{ name }}!</h1>
diff --git a/docs/getting_started/quick_glance/json/hello_world.pt b/docs/getting_started/quick_glance/json/hello_world.pt
index 0cf20d076..711054aa9 100644
--- a/docs/getting_started/quick_glance/json/hello_world.pt
+++ b/docs/getting_started/quick_glance/json/hello_world.pt
@@ -1,5 +1,5 @@
+<!DOCTYPE html>
<html lang="en">
-<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Quick Glance</title>
<!-- Start Link 1 -->
diff --git a/docs/getting_started/quick_glance/static_assets/hello_world.jinja2 b/docs/getting_started/quick_glance/static_assets/hello_world.jinja2
index 3d0f28c1f..f6862e618 100644
--- a/docs/getting_started/quick_glance/static_assets/hello_world.jinja2
+++ b/docs/getting_started/quick_glance/static_assets/hello_world.jinja2
@@ -1,8 +1,8 @@
+<!DOCTYPE html>
<html lang="en">
-<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Quick Glance</title>
- <link rel="stylesheet" href="/static/app.css" />
+ <link rel="stylesheet" href="/static/app.css"/>
</head>
<body>
<h1>Hello {{ name }}!</h1>
diff --git a/docs/getting_started/quick_glance/static_assets/hello_world.pt b/docs/getting_started/quick_glance/static_assets/hello_world.pt
index 0cf20d076..1797146eb 100644
--- a/docs/getting_started/quick_glance/static_assets/hello_world.pt
+++ b/docs/getting_started/quick_glance/static_assets/hello_world.pt
@@ -1,6 +1,5 @@
-<html lang="en">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
+<!DOCTYPE html>
+<html lang="en"><head>
<title>Quick Glance</title>
<!-- Start Link 1 -->
<link rel="stylesheet" href="/static/app.css" />
diff --git a/docs/getting_started/quick_glance/templating/hello_world.pt b/docs/getting_started/quick_glance/templating/hello_world.pt
index 8860df26a..ae14f447d 100644
--- a/docs/getting_started/quick_glance/templating/hello_world.pt
+++ b/docs/getting_started/quick_glance/templating/hello_world.pt
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<html lang="en">
<head>
<title>Quick Glance</title>
diff --git a/docs/getting_started/quick_glance/view_classes/app.py b/docs/getting_started/quick_glance/view_classes/app.py
index c29311aa5..468c8c29e 100644
--- a/docs/getting_started/quick_glance/view_classes/app.py
+++ b/docs/getting_started/quick_glance/view_classes/app.py
@@ -1,30 +1,13 @@
from wsgiref.simple_server import make_server
-
from pyramid.config import Configurator
-from pyramid.view import view_config
-
-
-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]
-
if __name__ == '__main__':
config = Configurator()
+ # Start Routes 1
config.add_route('hello', '/howdy/{name}')
- config.add_route('hello_json', 'hello.json')
- config.add_static_view(name='static', path='static')
+ # End Routes 1
config.include('pyramid_jinja2')
- config.scan()
+ config.scan('views')
app = config.make_wsgi_app()
server = make_server('0.0.0.0', 6543, app)
server.serve_forever() \ No newline at end of file
diff --git a/docs/getting_started/quick_glance/view_classes/delete.jinja2 b/docs/getting_started/quick_glance/view_classes/delete.jinja2
new file mode 100644
index 000000000..ba45b7d16
--- /dev/null
+++ b/docs/getting_started/quick_glance/view_classes/delete.jinja2
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <title>Delete World</title>
+</head>
+<body>
+<h1>Delete {{ view.name }}!</h1>
+</body>
+</html> \ No newline at end of file
diff --git a/docs/getting_started/quick_glance/view_classes/edit.jinja2 b/docs/getting_started/quick_glance/view_classes/edit.jinja2
new file mode 100644
index 000000000..ce0eb5bd1
--- /dev/null
+++ b/docs/getting_started/quick_glance/view_classes/edit.jinja2
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <title>Edit World</title>
+</head>
+<body>
+<h1>Edit {{ view.name }}!</h1>
+</body>
+</html> \ No newline at end of file
diff --git a/docs/getting_started/quick_glance/view_classes/hello.jinja2 b/docs/getting_started/quick_glance/view_classes/hello.jinja2
new file mode 100644
index 000000000..3446b96ce
--- /dev/null
+++ b/docs/getting_started/quick_glance/view_classes/hello.jinja2
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <title>Hello World</title>
+</head>
+<body>
+<h1>Hello {{ view.name }}!</h1>
+<!-- Start Form 1 -->
+<form method="POST"
+ action="{{ request.current_route_url() }}">
+ <input name="new_name"/>
+ <input type="submit" name="form.edit" value="Save"/>
+ <input type="submit" name="form.delete" value="Delete"/>
+</form>
+<!-- End Form 1 -->
+</body>
+</html> \ No newline at end of file
diff --git a/docs/getting_started/quick_glance/view_classes/views.py b/docs/getting_started/quick_glance/view_classes/views.py
new file mode 100644
index 000000000..62556142e
--- /dev/null
+++ b/docs/getting_started/quick_glance/view_classes/views.py
@@ -0,0 +1,32 @@
+from pyramid.view import (
+ view_config,
+ view_defaults
+ )
+
+
+# Start View 1
+# One route, at /howdy/amy, so don't repeat on each @view_config
+@view_defaults(route_name='hello')
+class HelloWorldViews:
+ def __init__(self, request):
+ self.request = request
+ # Our templates can now say {{ view.name }}
+ self.name = request.matchdict['name']
+
+ # Retrieving /howdy/amy the first time
+ @view_config(renderer='hello.jinja2')
+ def hello_view(self):
+ return dict()
+
+ # Posting to /howdy/amy via the "Edit" submit button
+ @view_config(request_param='form.edit', renderer='edit.jinja2')
+ def edit_view(self):
+ print('Edited')
+ return dict()
+
+ # Posting to /howdy/amy via the "Delete" submit button
+ @view_config(request_param='form.delete', renderer='delete.jinja2')
+ def delete_view(self):
+ print('Deleted')
+ return dict()
+ # End View 1 \ No newline at end of file
diff --git a/docs/getting_started/scaffolds.rst b/docs/getting_started/scaffolds.rst
index af26ab6d6..52101495e 100644
--- a/docs/getting_started/scaffolds.rst
+++ b/docs/getting_started/scaffolds.rst
@@ -2,9 +2,109 @@
Starting New Projects 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. You run a command, perhaps answer some
+questions, and a sample project is generated for you. Not just Pyramid
+itself: add-ons such as ``pyramid_jinja2`` (or your own projects) can
+register their own scaffolds.
+
+
+
Pyramid projects are organized using normal Python facilities for
projects. Normal, though, is in the eye of the beholder. This chapter
shows how to use scaffolds to automate the boilerplate and quickly
start development of a new project.
Topics: scaffolds, packaging, virtual environments
+
+Pyramid's ``pcreate`` command is used to generate a 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
+ $ python ./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. \ No newline at end of file
diff --git a/docs/getting_started/views.rst b/docs/getting_started/views.rst
index 347d5aae7..827778a66 100644
--- a/docs/getting_started/views.rst
+++ b/docs/getting_started/views.rst
@@ -1,3 +1,40 @@
================================
Handling Web Requests With Views
================================
+
+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,
+or a form might submit to different targets, or a REST handler might
+cover different operations.
+
+Grouping these together makes logical sense. A view class lets you
+group views, centralize some repetitive defaults, share some state
+assignments, and use helper functions as class methods.
+
+As an example, imagine we have some views around saying hello to a
+person, then editing that person or perhaps deleting that person. They
+might logically belong together. We could do these as independent
+functions, but let's do them together as a view class:
+
+.. literalinclude:: quick_glance/view_classes/views.py
+ :start-after: Start View 1
+ :end-before: End View 1
+
+...and some routes that wire up the views to URLs:
+
+.. literalinclude:: quick_glance/view_classes/app.py
+ :start-after: Start Routes 1
+ :end-before: End Routes 1
+
+...and a form in ``hello_world.jinja2`` that submits to the second view:
+
+.. literalinclude:: quick_glance/view_classes/hello_world.jinja2
+ :language: html
+ :start-after: Start Form 1
+ :end-before: End Form 1
+
+Just to review:
+
+- The ``/howdy/amy`` URL matches the ``hello`` route, handled by the
+ ``hello_view`` class method. \ No newline at end of file