diff options
| author | John Shipman <john@rainbow.nmt.edu> | 2011-01-15 14:45:17 -0700 |
|---|---|---|
| committer | John Shipman <john@rainbow.nmt.edu> | 2011-01-15 14:45:17 -0700 |
| commit | 6471d307be249dc2aa22ab65128e8c2a0404ff79 (patch) | |
| tree | b2fa9f8700225df0da5624a109cdfc851e0a2776 /docs/tutorials/wiki2 | |
| parent | a063aff1b0a9fe1f9d8c4a4baeade6453695f171 (diff) | |
| download | pyramid-6471d307be249dc2aa22ab65128e8c2a0404ff79.tar.gz pyramid-6471d307be249dc2aa22ab65128e8c2a0404ff79.tar.bz2 pyramid-6471d307be249dc2aa22ab65128e8c2a0404ff79.zip | |
General reformatting of the wiki and wiki2 tutorials to eliminate
any overly long lines in the PDF rendering.
Changes to .rst files:
(docs/tutorials/wiki/authorization.rst)
(docs/tutorials/wiki/definingviews.rst)
(docs/tutorials/wiki2/authorization.rst)
(docs/tutorials/wiki2/definingviews.rst)
1. For included templates, added :tab-width: 2 options.
2. wiki2/authorization.rst: Wrong markup for file names __init__.py and
views.py just after the subhead "Adding security.py".
Changes to .py files: Folded a few long lines.
(docs/tutorials/wiki/src/basiclayout/tutorial/views.py)
(docs/tutorials/wiki/src/authorization/tutorial/views.py)
(docs/tutorials/wiki/src/views/tutorial/views.py)
(docs/tutorials/wiki2/src/basiclayout/tutorial/models.py)
(docs/tutorials/wiki2/src/models/tutorial/models.py)
Changes to .pt files: Broke long lines; reformatted for 2-space
indentation using tabs.
(docs/tutorials/wiki/src/authorization/tutorial/templates/edit.pt)
(docs/tutorials/wiki/src/authorization/tutorial/templates/login.pt)
(docs/tutorials/wiki/src/authorization/tutorial/templates/view.pt)
(docs/tutorials/wiki/src/views/tutorial/templates/edit.pt)
(docs/tutorials/wiki/src/views/tutorial/templates/view.pt)
(docs/tutorials/wiki2/src/authorization/tutorial/templates/edit.pt)
(docs/tutorials/wiki2/src/authorization/tutorial/templates/login.pt)
(docs/tutorials/wiki2/src/authorization/tutorial/templates/view.pt)
(docs/tutorials/wiki2/src/views/tutorial/templates/edit.pt)
(docs/tutorials/wiki2/src/views/tutorial/templates/view.pt)
Diffstat (limited to 'docs/tutorials/wiki2')
9 files changed, 474 insertions, 74 deletions
diff --git a/docs/tutorials/wiki2/authorization.rst b/docs/tutorials/wiki2/authorization.rst index 5b07fe788..e3a4d5db4 100644 --- a/docs/tutorials/wiki2/authorization.rst +++ b/docs/tutorials/wiki2/authorization.rst @@ -125,7 +125,7 @@ Adding ``security.py`` ~~~~~~~~~~~~~~~~~~~~~~ Add a ``security.py`` module within your package (in the same directory as -"__init__.py", "views.py", etc) with the following content: +:file:`__init__.py`, :file:`views.py`, etc) with the following content: .. literalinclude:: src/authorization/tutorial/security.py :linenos: @@ -203,6 +203,7 @@ referred to within the login view we just added to ``login.py``. .. literalinclude:: src/authorization/tutorial/templates/login.pt :language: xml + :tab-width: 2 Change ``view.pt`` and ``edit.pt`` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -260,11 +261,13 @@ Our ``edit.pt`` template will look something like this when we're done: .. literalinclude:: src/authorization/tutorial/templates/edit.pt :language: xml + :tab-width: 2 Our ``view.pt`` template will look something like this when we're done: .. literalinclude:: src/authorization/tutorial/templates/view.pt :language: xml + :tab-width: 2 Revisiting the Application --------------------------- @@ -275,5 +278,351 @@ of hitting an edit or add page and submitting the login form with the hand corner. When we click it, we're logged out, and redirected back to the front page. +Overall flow of an authentication +--------------------------------- + +Now that you have seen all the pieces of the authentication +mechanism, here are some examples that show how they all work +together. + +#. Failed login: The user requests ``/FrontPage/edit_page``. The + site presents the login form. The user enters ``editor`` as + the login, but enters an invalid password ``bad``. + The site redisplays the login form with the message "Failed + login". See :ref:`failed_login`. + +#. The user again requests ``/FrontPage/edit_page``. The site + presents the login form, and this time the user enters + login ``editor`` and password ``editor``. The site presents + the edit form with the content of ``/FrontPage``. The user + makes some changes and saves them. See :ref:`good_login`. + +#. The user again revisits ``/FrontPage/edit_page``. The site + goes immediately to the edit form without requesting + credentials. See :ref:`revisit`. + +#. The user clicks the ``Logout`` link. See :ref:`logging_out`. + +.. _failed_login: + +Failed login +~~~~~~~~~~~~ + +The process starts when the user enters URL +``http://localhost:6543/FrontPage/edit_page``. Let's assume that +this is the first request ever made to the application and the +page database is empty except for the ``Page`` instance created +for the front page by the ``initialize_sql`` function in +:file:`models.py`. + +This process involves two complete request/response cycles. + +1. From the front page, the user clicks :guilabel:`Edit page`. + The request is to ``/FrontPage/edit_page``. The view callable + is ``login.login``. The response is the ``login.pt`` template + with blank fields. + +2. The user enters invalid credentials and clicks :guilabel:`Log + in`. A ``POST`` request is sent to ``/FrontPage/edit_page``. + The view callable is again ``login.login``. The response is + the ``login.pt`` template showing the message "Failed login", + with the entry fields displaying their former values. + +Cycle 1: + +#. During URL dispatch, the route ``'/{pagename}/edit_page'`` is + considered for matching. The associated view has a + ``view_permission='edit'`` permission attached, so the + dispatch logic has to verify that the user has that permission + or the route is not considered to match. + + The context for all route matching comes from the configured + root factory, :meth:`RootFactory` in :file:`models.py`. + This class has an ``__acl__`` attribute that defines the + access control list for all routes:: + + __acl__ = [ (Allow, Everyone, 'view'), + (Allow, 'group:editors', 'edit') ] + + In practice, this means that for any route that requires the + ``edit`` permission, the user must be authenticated and + have the ``group:editors`` principal or the route is not + considered to match. + +#. To find the list of the user's principals, the authorization + first policy checks to see if the user has a + ``paste.auth.auth_tkt`` cookie. Since the user has never been + to the site, there is no such cookie, and the user is + considered to be unauthenticated. +#. Since the user is unauthenticated, the ``groupfinder`` + function in :file:`security.py` is called with ``None`` as its + ``userid`` argument. The function returns an empty list of + principals. + +#. Because that list does not contain the ``group:editors`` + principal, the ``'/{pagename}/edit_page'`` route's ``edit`` + permission fails, and the route does not match. +#. Because no routes match, the `forbidden view` callable is + invoked: the ``login`` function in module ``login.py``. + +#. Inside the ``login`` function, the value of ``login_url`` is + ``http://localhost:6543/login``, and the value of + ``referrer`` is ``http://localhost:6543/FrontPage/edit_page``. + + Because ``request.params`` has no key for ``'came_from'``, the + variable ``came_from`` is also set to + ``http://localhost:6543/FrontPage/edit_page``. Variables + ``message``, ``login``, and ``password`` are set to the empty + string. + + Because ``request.params`` has no key for + ``'form.submitted'``, the ``login`` function returns this + dictionary:: + + {'message': '', 'url':'http://localhost:6543/login', + 'came_from':'http://localhost:6543/FrontPage/edit_page', + 'login':'', 'password':''} + +#. This dictionary is used to render the ``login.pt`` template. + In the form, the ``action`` attribute is + ``http://localhost:6543/login``, and the value of + ``came_from`` is included in that form as a hidden field + by this line in the template:: + + <input type="hidden" name="came_from" value="${came_from}"/> + +Cycle 2: + +#. The user enters incorrect credentials and clicks the + :guilabel:`Log in` button, which does a ``POST`` request to + URL ``http://localhost:6543/login``. The name of the + :guilabel:`Log in` button in this form is ``form.submitted``. + +#. The route with pattern ``'/login'`` matches this URL, so + control is passed again to the ``login`` view callable. + +#. The ``login_url`` and ``referrer`` have the same value + this time (``http://localhost:6543/login``), so variable + ``referrer`` is set to ``'/'``. + + Since ``request.params`` does have a key ``'form.submitted'``, + the values of ``login`` and ``password`` are retrieved from + ``request.params``. + + Because the login and password do not match any of the entries + in the ``USERS`` dictionary in ``security.py``, variable + ``message`` is set to ``'Failed login'``. + + The view callable returns this dictionary:: + + {'message':'Failed login', + 'url':'http://localhost:6543/login', 'came_from':'/', + 'login':'editor', 'password':'bad'} + +#. The ``login.pt`` template is rendered using those values. + +.. _good_login: + +Successful login +~~~~~~~~~~~~~~~~ + +In this scenario, the user again requests URL +``/FrontPage/edit_page``. + +This process involves four complete request/response cycles. + +1. The user clicks :guilabel:`Edit page`. The view callable is + ``login.login``. The response is template ``login.pt``, + with all the fields blank. + +2. The user enters valid credentials and clicks :guilabel:`Log in`. + The view callable is ``login.login``. The response is a + redirect to ``/FrontPage/edit_page``. + +3. The view callable is ``views.edit_page``. The response + renders template ``edit.pt``, displaying the current page + content. + +4. The user edits the content and clicks :guilabel:`Save`. + The view callable is ``views.edit_page``. The response + is a redirect to ``/FrontPage``. + +Execution proceeds as in :ref:`failed_login`, up to the point +where the password ``editor`` is successfully matched against the +value from the ``USERS`` dictionary. + +Cycle 2: + +#. Within the ``login.login`` view callable, the value of + ``login_url`` is ``http://localhost:6543/login``, and the + value of ``referrer`` is ``'/'``, and ``came_from`` is + ``http://localhost:6543/FrontPage/edit_page`` when this block + is executed: + + .. code-block:: python + + if USERS.get(login) == password: + headers = remember(request, login) + return HTTPFound(location=came_from, headers=headers) + +#. Because the password matches this time, + :mod:`pyramid.security.remember` returns a sequence of header + tuples that will set a ``paste.auth.auth_tkt`` authentication + cookie in the user's browser for the login ``'editor'``. + +#. The ``HTTPFound`` exception returns a response that redirects + the browser to ``http://localhost:6543/FrontPage/edit_page``, + including the headers that set the authentication cookie. + +Cycle 3: + +#. Route pattern ``'/{pagename}/edit_page'`` matches this URL, + but the corresponding view is restricted by an ``'edit'`` + permission. + +#. Because the user now has an authentication cookie defining + their login name as ``'editor'``, the ``groupfinder`` function + is called with that value as its ``userid`` argument. + +#. The ``groupfinder`` function returns the list + ``['group:editors']``. This satisfies the access control + entry ``(Allow, 'group:editors', 'edit')``, which grants the + ``edit`` permission. Thus, this route matches, and control + passes to view callable ``edit_page``. + +#. Within ``edit_page``, ``name`` is set to ``'FrontPage'``, the + page name from ``request.matchdict['pagename']``, and + ``page`` is set to an instance of :class:`models.Page` + that holds the current content of ``FrontPage``. + +#. Since this request did not come from a form, + ``request.params`` does not have a key for + ``'form.submitted'``. + +#. The ``edit_page`` function calls + :meth:`pyramid.security.authenticated_userid` to find out + whether the user is authenticated. Because of the cookies + set previously, the variable ``logged_in`` is set to + the userid ``'editor'``. + +#. The ``edit_page`` function returns this dictionary:: + + {'page':page, 'logged_in':'editor', + 'save_url':'http://localhost:6543/FrontPage/edit_page'} + +#. Template :file:`edit.pt` is rendered with those values. + Among other features of this template, these lines + cause the inclusion of a :guilabel:`Logout` link:: + + <span tal:condition="logged_in"> + <a href="${request.application_url}/logout">Logout</a> + </span> + + For the example case, this link will refer to + ``http://localhost:6543/logout``. + + These lines of the template display the current page's + content in a form whose ``action`` attribute is + ``http://localhost:6543/FrontPage/edit_page``:: + + <form action="${save_url}" method="post"> + <textarea name="body" tal:content="page.data" rows="10" cols="60"/> + <input type="submit" name="form.submitted" value="Save"/> + </form> + +Cycle 4: + +#. The user edits the page content and clicks + :guilabel:`Save`. + +#. URL ``http://localhost:6543/FrontPage/edit_page`` goes through + the same routing as before, up until the line that checks + whether ``request.params`` has a key ``'form.submitted'``. + This time, within the ``edit_page`` view callable, these + lines are executed:: + + page.data = request.params['body'] + session.add(page) + return HTTPFound(location = route_url('view_page', request, + pagename=name)) + + The first two lines replace the old page content with the + contents of the ``body`` text area from the form, and then + update the page stored in the database. The third line + causes a response that redirects the browser to + ``http://localhost:6543/FrontPage``. + +.. _revisit: + +Revisiting after authentication +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +In this case, the user has an authentication cookie set in their +browser that specifies their login as ``'editor'``. The +requested URL is ``http://localhost:6543/FrontPage/edit_page``. + +This process requires two request/response cycles. + +1. The user clicks :guilabel:`Edit page`. The view callable is + ``views.edit_page``. The response is ``edit.pt``, showing + the current page content. + +2. The user edits the content and clicks :guilabel:`Save`. + The view callable is ``views.edit_page``. The response is + a redirect to ``/Frontpage``. + +Cycle 1: + +#. The route with pattern ``/{pagename}/edit_page`` matches the + URL, and because of the authentication cookie, ``groupfinder`` + returns a list containing the ``group:editors`` principal, + which ``models.RootFactory.__acl__`` uses to grant the + ``edit`` permission, so this route matches and dispatches + to the view callable :meth:`views.edit_page`. + +#. In ``edit_page``, because the request did not come from a form + submission, ``request.params`` has no key for + ``'form.submitted'``. + +#. The variable ``logged_in`` is set to the login name + ``'editor'`` by calling ``authenticated_userid``, which + extracts it from the authentication cookie. + +#. The function returns this dictionary:: + + {'page':page, + 'save_url':'http://localhost:6543/FrontPage/edit_page', + 'logged_in':'editor'} + +#. Template :file:`edit.pt` is rendered with the values from + that dictionary. Because of the presence of the + ``'logged_in'`` entry, a :guilabel:`Logout` link appears. + +Cycle 2: + +#. The user edits the page content and clicks :guilabel:`Save`. + +#. The ``POST`` operation works as in :ref:`good_login`. + +.. _logging_out: + +Logging out +~~~~~~~~~~~ + +This process starts with a request URL +``http://localhost:6543/logout``. + +#. The route with pattern ``'/logout'`` matches and dispatches + to the view callable ``logout`` in :file:`login.py`. + +#. The call to :meth:`pyramid.security.forget` returns a list of + header tuples that will, when returned with the response, + cause the browser to delete the user's authentication cookie. + +#. The view callable returns an ``HTTPFound`` exception that + redirects the browser to named route ``view_wiki``, which + will translate to URL ``http://localhost:6543``. It + also passes along the headers that delete the + authentication cookie. diff --git a/docs/tutorials/wiki2/definingviews.rst b/docs/tutorials/wiki2/definingviews.rst index d4417ed0b..acf539e1a 100644 --- a/docs/tutorials/wiki2/definingviews.rst +++ b/docs/tutorials/wiki2/definingviews.rst @@ -213,6 +213,7 @@ the below: .. literalinclude:: src/views/tutorial/templates/view.pt :language: xml + :tab-width: 2 .. note:: The names available for our use in a template are always those that are present in the dictionary returned by the view @@ -240,6 +241,8 @@ the below: .. literalinclude:: src/views/tutorial/templates/edit.pt :language: xml + :tab-width: 2 + Static Assets ------------- diff --git a/docs/tutorials/wiki2/src/authorization/tutorial/templates/edit.pt b/docs/tutorials/wiki2/src/authorization/tutorial/templates/edit.pt index e8c59eb10..cea9b4932 100644 --- a/docs/tutorials/wiki2/src/authorization/tutorial/templates/edit.pt +++ b/docs/tutorials/wiki2/src/authorization/tutorial/templates/edit.pt @@ -1,16 +1,22 @@ -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> -<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" xmlns:tal="http://xml.zope.org/namespaces/tal"> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" + xmlns:tal="http://xml.zope.org/namespaces/tal"> <head> - <title>${page.name} - Pyramid tutorial wiki (based on TurboGears 20-Minute Wiki)</title> + <title>${page.name} - Pyramid tutorial wiki (based on + TurboGears 20-Minute Wiki)</title> <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/> <meta name="keywords" content="python web application" /> <meta name="description" content="pyramid web application" /> - <link rel="shortcut icon" href="${request.static_url('tutorial:static/favicon.ico')}" /> - <link rel="stylesheet" href="${request.static_url('tutorial:static/pylons.css')}" type="text/css" media="screen" charset="utf-8" /> - <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Neuton&subset=latin" type="text/css" media="screen" charset="utf-8" /> - <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Nobile:regular,italic,bold,bolditalic&subset=latin" type="text/css" media="screen" charset="utf-8" /> + <link rel="shortcut icon" + href="${request.static_url('tutorial:static/favicon.ico')}" /> + <link rel="stylesheet" + href="${request.static_url('tutorial:static/pylons.css')}" + type="text/css" media="screen" charset="utf-8" /> <!--[if lte IE 6]> - <link rel="stylesheet" href="${request.static_url('tutorial:static/ie6.css')}" type="text/css" media="screen" charset="utf-8" /> + <link rel="stylesheet" + href="${request.static_url('tutorial:static/ie6.css')}" + type="text/css" media="screen" charset="utf-8" /> <![endif]--> </head> <body> @@ -18,19 +24,22 @@ <div id="top-small"> <div class="top-small align-center"> <div> - <img src="${request.static_url('tutorial:static/pyramid-small.png')}" width="220" height="50" alt="pyramid" /> + <img width="220" height="50" alt="pyramid" + src="${request.static_url('tutorial:static/pyramid-small.png')}" /> </div> </div> </div> <div id="middle"> <div class="middle align-right"> <div id="left" class="app-welcome align-left"> - Editing <b><span tal:replace="page.name">Page Name Goes Here</span></b><br/> - You can return to the <a href="${request.application_url}">FrontPage</a>.<br/> + Editing <b><span tal:replace="page.name">Page Name + Goes Here</span></b><br/> + You can return to the + <a href="${request.application_url}">FrontPage</a>.<br/> </div> <div id="right" class="app-welcome align-right"> <span tal:condition="logged_in"> - <a href="${request.application_url}/logout">Logout</a> + <a href="${request.application_url}/logout">Logout</a> </span> </div> </div> @@ -38,9 +47,10 @@ <div id="bottom"> <div class="bottom"> <form action="${save_url}" method="post"> - <textarea name="body" tal:content="page.data" rows="10" cols="60"/><br/> - <input type="submit" name="form.submitted" value="Save"/> - </form> + <textarea name="body" tal:content="page.data" rows="10" + cols="60"/><br/> + <input type="submit" name="form.submitted" value="Save"/> + </form> </div> </div> </div> @@ -48,4 +58,4 @@ <div class="footer">© Copyright 2008-2011, Agendaless Consulting.</div> </div> </body> -</html>
\ No newline at end of file +</html> diff --git a/docs/tutorials/wiki2/src/authorization/tutorial/templates/login.pt b/docs/tutorials/wiki2/src/authorization/tutorial/templates/login.pt index 974e22f37..554b4ea87 100644 --- a/docs/tutorials/wiki2/src/authorization/tutorial/templates/login.pt +++ b/docs/tutorials/wiki2/src/authorization/tutorial/templates/login.pt @@ -1,16 +1,22 @@ -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> -<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" xmlns:tal="http://xml.zope.org/namespaces/tal"> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" + xmlns:tal="http://xml.zope.org/namespaces/tal"> <head> - <title>Login - Pyramid tutorial wiki (based on TurboGears 20-Minute Wiki)</title> + <title>Login - Pyramid tutorial wiki (based on TurboGears + 20-Minute Wiki)</title> <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/> <meta name="keywords" content="python web application" /> <meta name="description" content="pyramid web application" /> - <link rel="shortcut icon" href="${request.static_url('tutorial:static/favicon.ico')}" /> - <link rel="stylesheet" href="${request.static_url('tutorial:static/pylons.css')}" type="text/css" media="screen" charset="utf-8" /> - <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Neuton&subset=latin" type="text/css" media="screen" charset="utf-8" /> - <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Nobile:regular,italic,bold,bolditalic&subset=latin" type="text/css" media="screen" charset="utf-8" /> + <link rel="shortcut icon" + href="${request.static_url('tutorial:static/favicon.ico')}" /> + <link rel="stylesheet" + href="${request.static_url('tutorial:static/pylons.css')}" + type="text/css" media="screen" charset="utf-8" /> <!--[if lte IE 6]> - <link rel="stylesheet" href="${request.static_url('tutorial:static/ie6.css')}" type="text/css" media="screen" charset="utf-8" /> + <link rel="stylesheet" + href="${request.static_url('tutorial:static/ie6.css')}" + type="text/css" media="screen" charset="utf-8" /> <![endif]--> </head> <body> @@ -18,7 +24,8 @@ <div id="top-small"> <div class="top-small align-center"> <div> - <img src="${request.static_url('tutorial:static/pyramid-small.png')}" width="220" height="50" alt="pyramid" /> + <img width="220" height="50" alt="pyramid" + src="${request.static_url('tutorial:static/pyramid-small.png')}" /> </div> </div> </div> @@ -34,11 +41,12 @@ <div id="bottom"> <div class="bottom"> <form action="${url}" method="post"> - <input type="hidden" name="came_from" value="${came_from}"/> - <input type="text" name="login" value="${login}"/><br/> - <input type="password" name="password" value="${password}"/><br/> - <input type="submit" name="form.submitted" value="Log In"/> - </form> + <input type="hidden" name="came_from" value="${came_from}"/> + <input type="text" name="login" value="${login}"/><br/> + <input type="password" name="password" + value="${password}"/><br/> + <input type="submit" name="form.submitted" value="Log In"/> + </form> </div> </div> </div> @@ -46,4 +54,4 @@ <div class="footer">© Copyright 2008-2011, Agendaless Consulting.</div> </div> </body> -</html>
\ No newline at end of file +</html> diff --git a/docs/tutorials/wiki2/src/authorization/tutorial/templates/view.pt b/docs/tutorials/wiki2/src/authorization/tutorial/templates/view.pt index d0360429c..7d01aefb9 100644 --- a/docs/tutorials/wiki2/src/authorization/tutorial/templates/view.pt +++ b/docs/tutorials/wiki2/src/authorization/tutorial/templates/view.pt @@ -1,16 +1,22 @@ -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> -<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" xmlns:tal="http://xml.zope.org/namespaces/tal"> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" + xmlns:tal="http://xml.zope.org/namespaces/tal"> <head> - <title>${page.name} - Pyramid tutorial wiki (based on TurboGears 20-Minute Wiki)</title> + <title>${page.name} - Pyramid tutorial wiki (based on + TurboGears 20-Minute Wiki)</title> <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/> <meta name="keywords" content="python web application" /> <meta name="description" content="pyramid web application" /> - <link rel="shortcut icon" href="${request.static_url('tutorial:static/favicon.ico')}" /> - <link rel="stylesheet" href="${request.static_url('tutorial:static/pylons.css')}" type="text/css" media="screen" charset="utf-8" /> - <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Neuton&subset=latin" type="text/css" media="screen" charset="utf-8" /> - <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Nobile:regular,italic,bold,bolditalic&subset=latin" type="text/css" media="screen" charset="utf-8" /> + <link rel="shortcut icon" + href="${request.static_url('tutorial:static/favicon.ico')}" /> + <link rel="stylesheet" + href="${request.static_url('tutorial:static/pylons.css')}" + type="text/css" media="screen" charset="utf-8" /> <!--[if lte IE 6]> - <link rel="stylesheet" href="${request.static_url('tutorial:static/ie6.css')}" type="text/css" media="screen" charset="utf-8" /> + <link rel="stylesheet" + href="${request.static_url('tutorial:static/ie6.css')}" + type="text/css" media="screen" charset="utf-8" /> <![endif]--> </head> <body> @@ -18,19 +24,22 @@ <div id="top-small"> <div class="top-small align-center"> <div> - <img src="${request.static_url('tutorial:static/pyramid-small.png')}" width="220" height="50" alt="pyramid" /> + <img width="220" height="50" alt="pyramid" + src="${request.static_url('tutorial:static/pyramid-small.png')}" /> </div> </div> </div> <div id="middle"> <div class="middle align-right"> <div id="left" class="app-welcome align-left"> - Viewing <b><span tal:replace="page.name">Page Name Goes Here</span></b><br/> - You can return to the <a href="${request.application_url}">FrontPage</a>.<br/> + Viewing <b><span tal:replace="page.name">Page Name + Goes Here</span></b><br/> + You can return to the + <a href="${request.application_url}">FrontPage</a>.<br/> </div> <div id="right" class="app-welcome align-right"> <span tal:condition="logged_in"> - <a href="${request.application_url}/logout">Logout</a> + <a href="${request.application_url}/logout">Logout</a> </span> </div> </div> @@ -52,4 +61,4 @@ <div class="footer">© Copyright 2008-2011, Agendaless Consulting.</div> </div> </body> -</html>
\ No newline at end of file +</html> diff --git a/docs/tutorials/wiki2/src/basiclayout/tutorial/models.py b/docs/tutorials/wiki2/src/basiclayout/tutorial/models.py index 9da906752..4fd010c5c 100644 --- a/docs/tutorials/wiki2/src/basiclayout/tutorial/models.py +++ b/docs/tutorials/wiki2/src/basiclayout/tutorial/models.py @@ -12,7 +12,8 @@ from sqlalchemy.orm import sessionmaker from zope.sqlalchemy import ZopeTransactionExtension -DBSession = scoped_session(sessionmaker(extension=ZopeTransactionExtension())) +DBSession = scoped_session(sessionmaker( + extension=ZopeTransactionExtension())) Base = declarative_base() class MyModel(Base): diff --git a/docs/tutorials/wiki2/src/models/tutorial/models.py b/docs/tutorials/wiki2/src/models/tutorial/models.py index 23b8afab8..797fff929 100644 --- a/docs/tutorials/wiki2/src/models/tutorial/models.py +++ b/docs/tutorials/wiki2/src/models/tutorial/models.py @@ -12,7 +12,8 @@ from sqlalchemy.orm import sessionmaker from zope.sqlalchemy import ZopeTransactionExtension -DBSession = scoped_session(sessionmaker(extension=ZopeTransactionExtension())) +DBSession = scoped_session(sessionmaker( + extension=ZopeTransactionExtension())) Base = declarative_base() class Page(Base): diff --git a/docs/tutorials/wiki2/src/views/tutorial/templates/edit.pt b/docs/tutorials/wiki2/src/views/tutorial/templates/edit.pt index b45cea3c6..f8f63af3b 100644 --- a/docs/tutorials/wiki2/src/views/tutorial/templates/edit.pt +++ b/docs/tutorials/wiki2/src/views/tutorial/templates/edit.pt @@ -1,16 +1,22 @@ -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> -<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" xmlns:tal="http://xml.zope.org/namespaces/tal"> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" + xmlns:tal="http://xml.zope.org/namespaces/tal"> <head> - <title>${page.name} - Pyramid tutorial wiki (based on TurboGears 20-Minute Wiki)</title> + <title>${page.name} - Pyramid tutorial wiki (based on + TurboGears 20-Minute Wiki)</title> <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/> <meta name="keywords" content="python web application" /> <meta name="description" content="pyramid web application" /> - <link rel="shortcut icon" href="${request.static_url('tutorial:static/favicon.ico')}" /> - <link rel="stylesheet" href="${request.static_url('tutorial:static/pylons.css')}" type="text/css" media="screen" charset="utf-8" /> - <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Neuton&subset=latin" type="text/css" media="screen" charset="utf-8" /> - <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Nobile:regular,italic,bold,bolditalic&subset=latin" type="text/css" media="screen" charset="utf-8" /> + <link rel="shortcut icon" + href="${request.static_url('tutorial:static/favicon.ico')}" /> + <link rel="stylesheet" + href="${request.static_url('tutorial:static/pylons.css')}" + type="text/css" media="screen" charset="utf-8" /> <!--[if lte IE 6]> - <link rel="stylesheet" href="${request.static_url('tutorial:static/ie6.css')}" type="text/css" media="screen" charset="utf-8" /> + <link rel="stylesheet" + href="${request.static_url('tutorial:static/ie6.css')}" + type="text/css" media="screen" charset="utf-8" /> <![endif]--> </head> <body> @@ -18,15 +24,18 @@ <div id="top-small"> <div class="top-small align-center"> <div> - <img src="${request.static_url('tutorial:static/pyramid-small.png')}" width="220" height="50" alt="pyramid" /> + <img width="220" height="50" alt="pyramid" + src="${request.static_url('tutorial:static/pyramid-small.png')}" /> </div> </div> </div> <div id="middle"> <div class="middle align-right"> <div id="left" class="app-welcome align-left"> - Editing <b><span tal:replace="page.name">Page Name Goes Here</span></b><br/> - You can return to the <a href="${request.application_url}">FrontPage</a>.<br/> + Editing <b><span tal:replace="page.name">Page Name Goes + Here</span></b><br/> + You can return to the + <a href="${request.application_url}">FrontPage</a>.<br/> </div> <div id="right" class="app-welcome align-right"></div> </div> @@ -34,9 +43,10 @@ <div id="bottom"> <div class="bottom"> <form action="${save_url}" method="post"> - <textarea name="body" tal:content="page.data" rows="10" cols="60"/><br/> - <input type="submit" name="form.submitted" value="Save"/> - </form> + <textarea name="body" tal:content="page.data" rows="10" + cols="60"/><br/> + <input type="submit" name="form.submitted" value="Save"/> + </form> </div> </div> </div> @@ -44,4 +54,4 @@ <div class="footer">© Copyright 2008-2011, Agendaless Consulting.</div> </div> </body> -</html>
\ No newline at end of file +</html> diff --git a/docs/tutorials/wiki2/src/views/tutorial/templates/view.pt b/docs/tutorials/wiki2/src/views/tutorial/templates/view.pt index cacb58788..7c8a39f53 100644 --- a/docs/tutorials/wiki2/src/views/tutorial/templates/view.pt +++ b/docs/tutorials/wiki2/src/views/tutorial/templates/view.pt @@ -1,16 +1,22 @@ -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> -<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" xmlns:tal="http://xml.zope.org/namespaces/tal"> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" + xmlns:tal="http://xml.zope.org/namespaces/tal"> <head> - <title>${page.name} - Pyramid tutorial wiki (based on TurboGears 20-Minute Wiki)</title> + <title>${page.name} - Pyramid tutorial wiki (based on + TurboGears 20-Minute Wiki)</title> <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/> <meta name="keywords" content="python web application" /> <meta name="description" content="pyramid web application" /> - <link rel="shortcut icon" href="${request.static_url('tutorial:static/favicon.ico')}" /> - <link rel="stylesheet" href="${request.static_url('tutorial:static/pylons.css')}" type="text/css" media="screen" charset="utf-8" /> - <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Neuton&subset=latin" type="text/css" media="screen" charset="utf-8" /> - <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Nobile:regular,italic,bold,bolditalic&subset=latin" type="text/css" media="screen" charset="utf-8" /> + <link rel="shortcut icon" + href="${request.static_url('tutorial:static/favicon.ico')}" /> + <link rel="stylesheet" + href="${request.static_url('tutorial:static/pylons.css')}" + type="text/css" media="screen" charset="utf-8" /> <!--[if lte IE 6]> - <link rel="stylesheet" href="${request.static_url('tutorial:static/ie6.css')}" type="text/css" media="screen" charset="utf-8" /> + <link rel="stylesheet" + href="${request.static_url('tutorial:static/ie6.css')}" + type="text/css" media="screen" charset="utf-8" /> <![endif]--> </head> <body> @@ -18,15 +24,18 @@ <div id="top-small"> <div class="top-small align-center"> <div> - <img src="${request.static_url('tutorial:static/pyramid-small.png')}" width="220" height="50" alt="pyramid" /> + <img width="220" height="50" alt="pyramid" + src="${request.static_url('tutorial:static/pyramid-small.png')}" /> </div> </div> </div> <div id="middle"> <div class="middle align-right"> <div id="left" class="app-welcome align-left"> - Viewing <b><span tal:replace="page.name">Page Name Goes Here</span></b><br/> - You can return to the <a href="${request.application_url}">FrontPage</a>.<br/> + Viewing <b><span tal:replace="page.name">Page Name + Goes Here</span></b><br/> + You can return to the + <a href="${request.application_url}">FrontPage</a>.<br/> </div> <div id="right" class="app-welcome align-right"></div> </div> @@ -48,4 +57,4 @@ <div class="footer">© Copyright 2008-2011, Agendaless Consulting.</div> </div> </body> -</html>
\ No newline at end of file +</html> |
