summaryrefslogtreecommitdiff
path: root/docs/tutorials/wiki2
diff options
context:
space:
mode:
authorSteve Piercy <web@stevepiercy.com>2015-11-13 03:53:50 -0800
committerSteve Piercy <web@stevepiercy.com>2015-11-13 03:53:50 -0800
commitc172ec11f4a6420be7b2dbc3394721fb5854c491 (patch)
tree0c0a400d5aef9e3730216cb0b0ad5e685d350a51 /docs/tutorials/wiki2
parent414b67b45bab156b9738105e180908c4eee8600a (diff)
parent429529a09992554229ef7274bfc4f43394256105 (diff)
downloadpyramid-c172ec11f4a6420be7b2dbc3394721fb5854c491.tar.gz
pyramid-c172ec11f4a6420be7b2dbc3394721fb5854c491.tar.bz2
pyramid-c172ec11f4a6420be7b2dbc3394721fb5854c491.zip
Merge pull request #2122 from stevepiercy/feature/alchemy-scaffold-update
update wiki2/src/views and wiki2/definingviews.rst
Diffstat (limited to 'docs/tutorials/wiki2')
-rw-r--r--docs/tutorials/wiki2/definingviews.rst125
-rw-r--r--docs/tutorials/wiki2/src/views/development.ini4
-rw-r--r--docs/tutorials/wiki2/src/views/production.ini14
-rw-r--r--docs/tutorials/wiki2/src/views/setup.py2
-rw-r--r--docs/tutorials/wiki2/src/views/tutorial/__init__.py12
-rw-r--r--docs/tutorials/wiki2/src/views/tutorial/models.py25
-rw-r--r--docs/tutorials/wiki2/src/views/tutorial/scripts/initializedb.py25
-rw-r--r--docs/tutorials/wiki2/src/views/tutorial/templates/edit.pt69
-rw-r--r--docs/tutorials/wiki2/src/views/tutorial/templates/mytemplate.pt66
-rw-r--r--docs/tutorials/wiki2/src/views/tutorial/templates/view.pt69
-rw-r--r--docs/tutorials/wiki2/src/views/tutorial/tests.py175
-rw-r--r--docs/tutorials/wiki2/src/views/tutorial/views.py72
12 files changed, 141 insertions, 517 deletions
diff --git a/docs/tutorials/wiki2/definingviews.rst b/docs/tutorials/wiki2/definingviews.rst
index 0b495445a..08fa8f16b 100644
--- a/docs/tutorials/wiki2/definingviews.rst
+++ b/docs/tutorials/wiki2/definingviews.rst
@@ -14,7 +14,7 @@ and a user visits ``http://example.com/foo/bar``, our pattern would be matched
against ``/foo/bar`` and the ``matchdict`` would look like ``{'one':'foo',
'two':'bar'}``.
-Declaring Dependencies in Our ``setup.py`` File
+Declaring dependencies in our ``setup.py`` file
===============================================
The view code in our application will depend on a package which is not a
@@ -47,7 +47,7 @@ directory in which ``setup.py`` lives) and execute the following command.
On UNIX:
-.. code-block:: text
+.. code-block:: bash
$ cd tutorial
$ $VENV/bin/python setup.py develop
@@ -60,31 +60,32 @@ On Windows:
c:\pyramidtut\tutorial> %VENV%\Scripts\python setup.py develop
Success executing this command will end with a line to the console something
-like::
+like this::
Finished processing dependencies for tutorial==0.0
-Adding view functions in ``views.py``
-=====================================
+Adding view functions in ``views/default.py``
+=============================================
-It's time for a major change. Open ``tutorial/tutorial/views.py`` and edit it
-to look like the following:
+It's time for a major change. Open ``tutorial/tutorial/views/default.py`` and
+edit it to look like the following:
-.. literalinclude:: src/views/tutorial/views.py
+.. literalinclude:: src/views/tutorial/views/default.py
:linenos:
:language: python
- :emphasize-lines: 1-7,14,16-72
+ :emphasize-lines: 1-9,12-70
The highlighted lines need to be added or edited.
-We added some imports and created a regular expression to find "WikiWords".
+We added some imports, and created a regular expression to find "WikiWords".
We got rid of the ``my_view`` view function and its decorator that was added
when we originally rendered the ``alchemy`` scaffold. It was only an example
-and isn't relevant to our application.
+and isn't relevant to our application. We also delated the ``db_err_msg``
+string.
-Then we added four :term:`view callable` functions to our ``views.py``
-module:
+Then we added four :term:`view callable` functions to our ``views/default.py``
+module:
* ``view_wiki()`` - Displays the wiki itself. It will answer on the root URL.
* ``view_page()`` - Displays an individual page.
@@ -95,20 +96,20 @@ We'll describe each one briefly in the following sections.
.. note::
- There is nothing special about the filename ``views.py``. A project may
- have many view callables throughout its codebase in arbitrarily named
- files. Files implementing view callables often have ``view`` in their
- filenames (or may live in a Python subpackage of your application package
- named ``views``), but this is only by convention.
+ There is nothing special about the filename ``default.py``. A project may
+ have many view callables throughout its codebase in arbitrarily named files.
+ Files implementing view callables often have ``view`` in their filenames (or
+ may live in a Python subpackage of your application package named ``views``,
+ as in our case), but this is only by convention.
The ``view_wiki`` view function
-------------------------------
Following is the code for the ``view_wiki`` view function and its decorator:
-.. literalinclude:: src/views/tutorial/views.py
- :lines: 20-24
- :lineno-start: 20
+.. literalinclude:: src/views/tutorial/views/default.py
+ :lines: 17-20
+ :lineno-start: 17
:linenos:
:language: python
@@ -130,9 +131,9 @@ The ``view_page`` view function
Here is the code for the ``view_page`` view function and its decorator:
-.. literalinclude:: src/views/tutorial/views.py
- :lines: 25-45
- :lineno-start: 25
+.. literalinclude:: src/views/tutorial/views/default.py
+ :lines: 22-42
+ :lineno-start: 22
:linenos:
:language: python
@@ -158,17 +159,17 @@ template, and we return a dictionary with a number of arguments. The fact that
``view_page()`` returns a dictionary (as opposed to a :term:`response` object)
is a cue to :app:`Pyramid` that it should try to use a :term:`renderer`
associated with the view configuration to render a response. In our case, the
-renderer used will be the ``templates/view.pt`` template, as indicated in the
-``@view_config`` decorator that is applied to ``view_page()``.
+renderer used will be the ``templates/view.jinja2`` template, as indicated in
+the ``@view_config`` decorator that is applied to ``view_page()``.
The ``add_page`` view function
------------------------------
Here is the code for the ``add_page`` view function and its decorator:
-.. literalinclude:: src/views/tutorial/views.py
- :lines: 47-58
- :lineno-start: 47
+.. literalinclude:: src/views/tutorial/views/default.py
+ :lines: 44-55
+ :lineno-start: 44
:linenos:
:language: python
@@ -189,15 +190,15 @@ If the view execution *is* a result of a form submission (i.e., the expression
``'form.submitted' in request.params`` is ``True``), we grab the page body
from the form data, create a Page object with this page body and the name
taken from ``matchdict['pagename']``, and save it into the database using
-``DBSession.add``. We then redirect back to the ``view_page`` view for the
-newly created page.
+``request.dbession.add``. We then redirect back to the ``view_page`` view for
+the newly created page.
If the view execution is *not* a result of a form submission (i.e., the
expression ``'form.submitted' in request.params`` is ``False``), the view
callable renders a template. To do so, it generates a ``save_url`` which the
template uses as the form post URL during rendering. We're lazy here, so
-we're going to use the same template (``templates/edit.pt``) for the add
-view as well as the page edit view. To do so we create a dummy Page object
+we're going to use the same template (``templates/edit.jinja2``) for the add
+view as well as the page edit view. To do so we create a dummy ``Page`` object
in order to satisfy the edit form's desire to have *some* page object
exposed as ``page``. :app:`Pyramid` will render the template associated
with this view to a response.
@@ -207,14 +208,14 @@ The ``edit_page`` view function
Here is the code for the ``edit_page`` view function and its decorator:
-.. literalinclude:: src/views/tutorial/views.py
- :lines: 60-72
- :lineno-start: 60
+.. literalinclude:: src/views/tutorial/views/default.py
+ :lines: 57-69
+ :lineno-start: 57
:linenos:
:language: python
``edit_page()`` is invoked when a user clicks the "Edit this
-Page" button on the view form. It renders an edit form but it also acts as
+Page" button on the view form. It renders an edit form, but it also acts as
the handler for the form it renders. The ``matchdict`` attribute of the
request passed to the ``edit_page`` view will have a ``'pagename'`` key
matching the name of the page the user wants to edit.
@@ -234,49 +235,51 @@ Adding templates
================
The ``view_page``, ``add_page`` and ``edit_page`` views that we've added
-reference a :term:`template`. Each template is a :term:`Chameleon`
-:term:`ZPT` template. These templates will live in the ``templates``
-directory of our tutorial package. Chameleon templates must have a ``.pt``
-extension to be recognized as such.
+reference a :term:`template`. Each template is a :term:`Jinja2` template.
+These templates will live in the ``templates`` directory of our tutorial
+package. Jinja2 templates must have a ``.jinja2`` extension to be recognized
+as such.
-The ``view.pt`` template
-------------------------
+The ``view.jinja2`` template
+----------------------------
-Create ``tutorial/tutorial/templates/view.pt`` and add the following
+Create ``tutorial/tutorial/templates/view.jinja2`` and add the following
content:
-.. literalinclude:: src/views/tutorial/templates/view.pt
+.. literalinclude:: src/views/tutorial/templates/view.jinja2
:linenos:
+ :emphasize-lines: 36,38-40
:language: html
This template is used by ``view_page()`` for displaying a single
wiki page. It includes:
-- A ``div`` element that is replaced with the ``content`` value provided by
- the view (lines 36-38). ``content`` contains HTML, so the ``structure``
- keyword is used to prevent escaping it (i.e., changing ">" to "&gt;", etc.)
-- A link that points at the "edit" URL which invokes the ``edit_page`` view
- for the page being viewed (lines 40-42).
+- A variable that is replaced with the ``content`` value provided by the view
+ (line 36). ``content`` contains HTML, so the ``|safe`` filter is used to
+ prevent escaping it (e.g., changing ">" to "&gt;").
+- A link that points at the "edit" URL which invokes the ``edit_page`` view for
+ the page being viewed (lines 38-40).
-The ``edit.pt`` template
-------------------------
+The ``edit.jinja2`` template
+----------------------------
-Create ``tutorial/tutorial/templates/edit.pt`` and add the following
+Create ``tutorial/tutorial/templates/edit.jinja2`` and add the following
content:
-.. literalinclude:: src/views/tutorial/templates/edit.pt
+.. literalinclude:: src/views/tutorial/templates/edit.jinja2
:linenos:
+ :emphasize-lines: 42,44,47
:language: html
This template is used by ``add_page()`` and ``edit_page()`` for adding and
editing a wiki page. It displays a page containing a form that includes:
-- A 10 row by 60 column ``textarea`` field named ``body`` that is filled
- with any existing page data when it is rendered (line 45).
-- A submit button that has the name ``form.submitted`` (line 48).
+- A 10-row by 60-column ``textarea`` field named ``body`` that is filled with
+ any existing page data when it is rendered (line 44).
+- A submit button that has the name ``form.submitted`` (line 47).
The form POSTs back to the ``save_url`` argument supplied by the view (line
-43). The view will use the ``body`` and ``form.submitted`` values.
+42). The view will use the ``body`` and ``form.submitted`` values.
.. note:: Our templates use a ``request`` object that none of our tutorial
views return in their dictionary. ``request`` is one of several names that
@@ -284,7 +287,7 @@ The form POSTs back to the ``save_url`` argument supplied by the view (line
See :ref:`renderer_system_values` for information about other names that
are available by default when a template is used as a renderer.
-Static Assets
+Static assets
-------------
Our templates name static assets, including CSS and images. We don't need
@@ -299,7 +302,7 @@ subdirectories) and are just referred to by URL or by using the convenience
method ``static_url``, e.g.,
``request.static_url('<package>:static/foo.css')`` within templates.
-Adding Routes to ``__init__.py``
+Adding routes to ``__init__.py``
================================
The ``__init__.py`` file contains
@@ -340,7 +343,7 @@ something like:
.. literalinclude:: src/views/tutorial/__init__.py
:linenos:
- :emphasize-lines: 19-22
+ :emphasize-lines: 11-14
:language: python
The highlighted lines are the ones that need to be added or edited.
diff --git a/docs/tutorials/wiki2/src/views/development.ini b/docs/tutorials/wiki2/src/views/development.ini
index a9d53b296..99c4ff0fe 100644
--- a/docs/tutorials/wiki2/src/views/development.ini
+++ b/docs/tutorials/wiki2/src/views/development.ini
@@ -27,7 +27,7 @@ sqlalchemy.url = sqlite:///%(here)s/tutorial.sqlite
[server:main]
use = egg:waitress#main
-host = 0.0.0.0
+host = 127.0.0.1
port = 6543
###
@@ -68,4 +68,4 @@ level = NOTSET
formatter = generic
[formatter_generic]
-format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s
+format = %(asctime)s %(levelname)-5.5s [%(name)s:%(lineno)s][%(threadName)s] %(message)s
diff --git a/docs/tutorials/wiki2/src/views/production.ini b/docs/tutorials/wiki2/src/views/production.ini
index 4684d2f7a..97acfbd7d 100644
--- a/docs/tutorials/wiki2/src/views/production.ini
+++ b/docs/tutorials/wiki2/src/views/production.ini
@@ -1,3 +1,8 @@
+###
+# app configuration
+# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/environment.html
+###
+
[app:main]
use = egg:tutorial
@@ -16,7 +21,10 @@ use = egg:waitress#main
host = 0.0.0.0
port = 6543
-# Begin logging configuration
+###
+# logging configuration
+# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/logging.html
+###
[loggers]
keys = root, tutorial, sqlalchemy
@@ -51,6 +59,4 @@ level = NOTSET
formatter = generic
[formatter_generic]
-format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s
-
-# End logging configuration
+format = %(asctime)s %(levelname)-5.5s [%(name)s:%(lineno)s][%(threadName)s] %(message)s
diff --git a/docs/tutorials/wiki2/src/views/setup.py b/docs/tutorials/wiki2/src/views/setup.py
index 09bd63d33..d4e5a4072 100644
--- a/docs/tutorials/wiki2/src/views/setup.py
+++ b/docs/tutorials/wiki2/src/views/setup.py
@@ -10,7 +10,7 @@ with open(os.path.join(here, 'CHANGES.txt')) as f:
requires = [
'pyramid',
- 'pyramid_chameleon',
+ 'pyramid_jinja2',
'pyramid_debugtoolbar',
'pyramid_tm',
'SQLAlchemy',
diff --git a/docs/tutorials/wiki2/src/views/tutorial/__init__.py b/docs/tutorials/wiki2/src/views/tutorial/__init__.py
index 37cae1997..d28f09ca4 100644
--- a/docs/tutorials/wiki2/src/views/tutorial/__init__.py
+++ b/docs/tutorials/wiki2/src/views/tutorial/__init__.py
@@ -1,20 +1,12 @@
from pyramid.config import Configurator
-from sqlalchemy import engine_from_config
-
-from .models import (
- DBSession,
- Base,
- )
def main(global_config, **settings):
""" This function returns a Pyramid WSGI application.
"""
- engine = engine_from_config(settings, 'sqlalchemy.')
- DBSession.configure(bind=engine)
- Base.metadata.bind = engine
config = Configurator(settings=settings)
- config.include('pyramid_chameleon')
+ config.include('pyramid_jinja2')
+ config.include('.models.meta')
config.add_static_view('static', 'static', cache_max_age=3600)
config.add_route('view_wiki', '/')
config.add_route('view_page', '/{pagename}')
diff --git a/docs/tutorials/wiki2/src/views/tutorial/models.py b/docs/tutorials/wiki2/src/views/tutorial/models.py
deleted file mode 100644
index f028c917a..000000000
--- a/docs/tutorials/wiki2/src/views/tutorial/models.py
+++ /dev/null
@@ -1,25 +0,0 @@
-from sqlalchemy import (
- Column,
- Integer,
- Text,
- )
-
-from sqlalchemy.ext.declarative import declarative_base
-
-from sqlalchemy.orm import (
- scoped_session,
- sessionmaker,
- )
-
-from zope.sqlalchemy import ZopeTransactionExtension
-
-DBSession = scoped_session(sessionmaker(extension=ZopeTransactionExtension()))
-Base = declarative_base()
-
-
-class Page(Base):
- """ The SQLAlchemy declarative model class for a Page object. """
- __tablename__ = 'pages'
- id = Column(Integer, primary_key=True)
- name = Column(Text, unique=True)
- data = Column(Text)
diff --git a/docs/tutorials/wiki2/src/views/tutorial/scripts/initializedb.py b/docs/tutorials/wiki2/src/views/tutorial/scripts/initializedb.py
index 23a5f13f4..4aac4a848 100644
--- a/docs/tutorials/wiki2/src/views/tutorial/scripts/initializedb.py
+++ b/docs/tutorials/wiki2/src/views/tutorial/scripts/initializedb.py
@@ -2,36 +2,41 @@ import os
import sys
import transaction
-from sqlalchemy import engine_from_config
-
from pyramid.paster import (
get_appsettings,
setup_logging,
)
-from ..models import (
- DBSession,
- Page,
+from ..models.meta import (
Base,
+ get_session,
+ get_engine,
+ get_dbmaker,
)
+from ..models.mymodel import Page
def usage(argv):
cmd = os.path.basename(argv[0])
- print('usage: %s <config_uri>\n'
+ print('usage: %s <config_uri> [var=value]\n'
'(example: "%s development.ini")' % (cmd, cmd))
sys.exit(1)
def main(argv=sys.argv):
- if len(argv) != 2:
+ if len(argv) < 2:
usage(argv)
config_uri = argv[1]
setup_logging(config_uri)
settings = get_appsettings(config_uri)
- engine = engine_from_config(settings, 'sqlalchemy.')
- DBSession.configure(bind=engine)
+
+ engine = get_engine(settings)
+ dbmaker = get_dbmaker(engine)
+
+ dbsession = get_session(transaction.manager, dbmaker)
+
Base.metadata.create_all(engine)
+
with transaction.manager:
model = Page(name='FrontPage', data='This is the front page')
- DBSession.add(model)
+ dbsession.add(model)
diff --git a/docs/tutorials/wiki2/src/views/tutorial/templates/edit.pt b/docs/tutorials/wiki2/src/views/tutorial/templates/edit.pt
deleted file mode 100644
index c0c1b6c20..000000000
--- a/docs/tutorials/wiki2/src/views/tutorial/templates/edit.pt
+++ /dev/null
@@ -1,69 +0,0 @@
-<!DOCTYPE html>
-<html lang="${request.locale_name}">
- <head>
- <meta charset="utf-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <meta name="description" content="pyramid web application">
- <meta name="author" content="Pylons Project">
- <link rel="shortcut icon" href="${request.static_url('tutorial:static/pyramid-16x16.png')}">
-
- <title>${page.name} - Pyramid tutorial wiki (based on
- TurboGears 20-Minute Wiki)</title>
-
- <!-- Bootstrap core CSS -->
- <link href="//oss.maxcdn.com/libs/twitter-bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet">
-
- <!-- Custom styles for this scaffold -->
- <link href="${request.static_url('tutorial:static/theme.css')}" rel="stylesheet">
-
- <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
- <!--[if lt IE 9]>
- <script src="//oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
- <script src="//oss.maxcdn.com/libs/respond.js/1.3.0/respond.min.js"></script>
- <![endif]-->
- </head>
- <body>
-
- <div class="starter-template">
- <div class="container">
- <div class="row">
- <div class="col-md-2">
- <img class="logo img-responsive" src="${request.static_url('tutorial:static/pyramid.png')}" alt="pyramid web framework">
- </div>
- <div class="col-md-10">
- <div class="content">
- <p>
- Editing <strong><span tal:replace="page.name">Page Name Goes
- Here</span></strong>
- </p>
- <p>You can return to the
- <a href="${request.application_url}">FrontPage</a>.
- </p>
- <form action="${save_url}" method="post">
- <div class="form-group">
- <textarea class="form-control" name="body" tal:content="page.data" rows="10" cols="60"></textarea>
- </div>
- <div class="form-group">
- <button type="submit" name="form.submitted" value="Save" class="btn btn-default">Save</button>
- </div>
- </form>
- </div>
- </div>
- </div>
- <div class="row">
- <div class="copyright">
- Copyright &copy; Pylons Project
- </div>
- </div>
- </div>
- </div>
-
-
- <!-- Bootstrap core JavaScript
- ================================================== -->
- <!-- Placed at the end of the document so the pages load faster -->
- <script src="//oss.maxcdn.com/libs/jquery/1.10.2/jquery.min.js"></script>
- <script src="//oss.maxcdn.com/libs/twitter-bootstrap/3.0.3/js/bootstrap.min.js"></script>
- </body>
-</html>
diff --git a/docs/tutorials/wiki2/src/views/tutorial/templates/mytemplate.pt b/docs/tutorials/wiki2/src/views/tutorial/templates/mytemplate.pt
deleted file mode 100644
index c9b0cec21..000000000
--- a/docs/tutorials/wiki2/src/views/tutorial/templates/mytemplate.pt
+++ /dev/null
@@ -1,66 +0,0 @@
-<!DOCTYPE html>
-<html lang="${request.locale_name}">
- <head>
- <meta charset="utf-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <meta name="description" content="pyramid web application">
- <meta name="author" content="Pylons Project">
- <link rel="shortcut icon" href="${request.static_url('tutorial:static/pyramid-16x16.png')}">
-
- <title>Alchemy Scaffold for The Pyramid Web Framework</title>
-
- <!-- Bootstrap core CSS -->
- <link href="//oss.maxcdn.com/libs/twitter-bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet">
-
- <!-- Custom styles for this scaffold -->
- <link href="${request.static_url('tutorial:static/theme.css')}" rel="stylesheet">
-
- <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
- <!--[if lt IE 9]>
- <script src="//oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
- <script src="//oss.maxcdn.com/libs/respond.js/1.3.0/respond.min.js"></script>
- <![endif]-->
- </head>
-
- <body>
-
- <div class="starter-template">
- <div class="container">
- <div class="row">
- <div class="col-md-2">
- <img class="logo img-responsive" src="${request.static_url('tutorial:static/pyramid.png')}" alt="pyramid web framework">
- </div>
- <div class="col-md-10">
- <div class="content">
- <h1><span class="font-semi-bold">Pyramid</span> <span class="smaller">Alchemy scaffold</span></h1>
- <p class="lead">Welcome to <span class="font-normal">${project}</span>, an&nbsp;application generated&nbsp;by<br>the <span class="font-normal">Pyramid Web Framework</span>.</p>
- </div>
- </div>
- </div>
- <div class="row">
- <div class="links">
- <ul>
- <li><i class="glyphicon glyphicon-bookmark icon-muted"></i><a href="http://docs.pylonsproject.org/projects/pyramid/en/latest/">Docs</a></li>
- <li><i class="glyphicon glyphicon-cog icon-muted"></i><a href="https://github.com/Pylons/pyramid">Github Project</a></li>
- <li><i class="glyphicon glyphicon-globe icon-muted"></i><a href="irc://irc.freenode.net#pyramid">IRC Channel</a></li>
- <li><i class="glyphicon glyphicon-home icon-muted"></i><a href="http://pylonsproject.org">Pylons Project</a></li>
- </ul>
- </div>
- </div>
- <div class="row">
- <div class="copyright">
- Copyright &copy; Pylons Project
- </div>
- </div>
- </div>
- </div>
-
-
- <!-- Bootstrap core JavaScript
- ================================================== -->
- <!-- Placed at the end of the document so the pages load faster -->
- <script src="//oss.maxcdn.com/libs/jquery/1.10.2/jquery.min.js"></script>
- <script src="//oss.maxcdn.com/libs/twitter-bootstrap/3.0.3/js/bootstrap.min.js"></script>
- </body>
-</html>
diff --git a/docs/tutorials/wiki2/src/views/tutorial/templates/view.pt b/docs/tutorials/wiki2/src/views/tutorial/templates/view.pt
deleted file mode 100644
index 0f564b16c..000000000
--- a/docs/tutorials/wiki2/src/views/tutorial/templates/view.pt
+++ /dev/null
@@ -1,69 +0,0 @@
-<!DOCTYPE html>
-<html lang="${request.locale_name}">
- <head>
- <meta charset="utf-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <meta name="description" content="pyramid web application">
- <meta name="author" content="Pylons Project">
- <link rel="shortcut icon" href="${request.static_url('tutorial:static/pyramid-16x16.png')}">
-
- <title>${page.name} - Pyramid tutorial wiki (based on
- TurboGears 20-Minute Wiki)</title>
-
- <!-- Bootstrap core CSS -->
- <link href="//oss.maxcdn.com/libs/twitter-bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet">
-
- <!-- Custom styles for this scaffold -->
- <link href="${request.static_url('tutorial:static/theme.css')}" rel="stylesheet">
-
- <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
- <!--[if lt IE 9]>
- <script src="//oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
- <script src="//oss.maxcdn.com/libs/respond.js/1.3.0/respond.min.js"></script>
- <![endif]-->
- </head>
- <body>
-
- <div class="starter-template">
- <div class="container">
- <div class="row">
- <div class="col-md-2">
- <img class="logo img-responsive" src="${request.static_url('tutorial:static/pyramid.png')}" alt="pyramid web framework">
- </div>
- <div class="col-md-10">
- <div class="content">
- <div tal:replace="structure content">
- Page text goes here.
- </div>
- <p>
- <a tal:attributes="href edit_url" href="">
- Edit this page
- </a>
- </p>
- <p>
- Viewing <strong><span tal:replace="page.name">
- Page Name Goes Here</span></strong>
- </p>
- <p>You can return to the
- <a href="${request.application_url}">FrontPage</a>.
- </p>
- </div>
- </div>
- </div>
- <div class="row">
- <div class="copyright">
- Copyright &copy; Pylons Project
- </div>
- </div>
- </div>
- </div>
-
-
- <!-- Bootstrap core JavaScript
- ================================================== -->
- <!-- Placed at the end of the document so the pages load faster -->
- <script src="//oss.maxcdn.com/libs/jquery/1.10.2/jquery.min.js"></script>
- <script src="//oss.maxcdn.com/libs/twitter-bootstrap/3.0.3/js/bootstrap.min.js"></script>
- </body>
-</html>
diff --git a/docs/tutorials/wiki2/src/views/tutorial/tests.py b/docs/tutorials/wiki2/src/views/tutorial/tests.py
index 9f01d2da5..b947e3bb1 100644
--- a/docs/tutorials/wiki2/src/views/tutorial/tests.py
+++ b/docs/tutorials/wiki2/src/views/tutorial/tests.py
@@ -3,144 +3,63 @@ import transaction
from pyramid import testing
-def _initTestingDB():
- from sqlalchemy import create_engine
- from tutorial.models import (
- DBSession,
- Page,
- Base
- )
- engine = create_engine('sqlite://')
- Base.metadata.create_all(engine)
- DBSession.configure(bind=engine)
- with transaction.manager:
- model = Page(name='FrontPage', data='This is the front page')
- DBSession.add(model)
- return DBSession
-
-def _registerRoutes(config):
- config.add_route('view_page', '{pagename}')
- config.add_route('edit_page', '{pagename}/edit_page')
- config.add_route('add_page', 'add_page/{pagename}')
-
-class ViewWikiTests(unittest.TestCase):
+
+def dummy_request(dbsession):
+ return testing.DummyRequest(dbsession=dbsession)
+
+
+class BaseTest(unittest.TestCase):
def setUp(self):
- self.config = testing.setUp()
- self.session = _initTestingDB()
+ self.config = testing.setUp(settings={
+ 'sqlalchemy.url': 'sqlite:///:memory:'
+ })
+ self.config.include('.models.meta')
+ settings = self.config.get_settings()
- def tearDown(self):
- self.session.remove()
- testing.tearDown()
+ from .models.meta import (
+ get_session,
+ get_engine,
+ get_dbmaker,
+ )
- def _callFUT(self, request):
- from tutorial.views import view_wiki
- return view_wiki(request)
+ self.engine = get_engine(settings)
+ dbmaker = get_dbmaker(self.engine)
- def test_it(self):
- _registerRoutes(self.config)
- request = testing.DummyRequest()
- response = self._callFUT(request)
- self.assertEqual(response.location, 'http://example.com/FrontPage')
+ self.session = get_session(transaction.manager, dbmaker)
-class ViewPageTests(unittest.TestCase):
- def setUp(self):
- self.session = _initTestingDB()
- self.config = testing.setUp()
+ def init_database(self):
+ from .models.meta import Base
+ Base.metadata.create_all(self.engine)
def tearDown(self):
- self.session.remove()
- testing.tearDown()
-
- def _callFUT(self, request):
- from tutorial.views import view_page
- return view_page(request)
-
- def test_it(self):
- from tutorial.models import Page
- request = testing.DummyRequest()
- request.matchdict['pagename'] = 'IDoExist'
- page = Page(name='IDoExist', data='Hello CruelWorld IDoExist')
- self.session.add(page)
- _registerRoutes(self.config)
- info = self._callFUT(request)
- self.assertEqual(info['page'], page)
- self.assertEqual(
- info['content'],
- '<div class="document">\n'
- '<p>Hello <a href="http://example.com/add_page/CruelWorld">'
- 'CruelWorld</a> '
- '<a href="http://example.com/IDoExist">'
- 'IDoExist</a>'
- '</p>\n</div>\n')
- self.assertEqual(info['edit_url'],
- 'http://example.com/IDoExist/edit_page')
-
-
-class AddPageTests(unittest.TestCase):
- def setUp(self):
- self.session = _initTestingDB()
- self.config = testing.setUp()
+ from .models.meta import Base
- def tearDown(self):
- self.session.remove()
testing.tearDown()
+ transaction.abort()
+ Base.metadata.create_all(self.engine)
+
+
+class TestMyViewSuccessCondition(BaseTest):
- def _callFUT(self, request):
- from tutorial.views import add_page
- return add_page(request)
-
- def test_it_notsubmitted(self):
- _registerRoutes(self.config)
- request = testing.DummyRequest()
- request.matchdict = {'pagename':'AnotherPage'}
- info = self._callFUT(request)
- self.assertEqual(info['page'].data,'')
- self.assertEqual(info['save_url'],
- 'http://example.com/add_page/AnotherPage')
-
- def test_it_submitted(self):
- from tutorial.models import Page
- _registerRoutes(self.config)
- request = testing.DummyRequest({'form.submitted':True,
- 'body':'Hello yo!'})
- request.matchdict = {'pagename':'AnotherPage'}
- self._callFUT(request)
- page = self.session.query(Page).filter_by(name='AnotherPage').one()
- self.assertEqual(page.data, 'Hello yo!')
-
-class EditPageTests(unittest.TestCase):
def setUp(self):
- self.session = _initTestingDB()
- self.config = testing.setUp()
+ super(TestMyViewSuccessCondition, self).setUp()
+ self.init_database()
- def tearDown(self):
- self.session.remove()
- testing.tearDown()
+ from .models.mymodel import MyModel
+
+ model = MyModel(name='one', value=55)
+ self.session.add(model)
+
+ def test_passing_view(self):
+ from .views.default import my_view
+ info = my_view(dummy_request(self.session))
+ self.assertEqual(info['one'].name, 'one')
+ self.assertEqual(info['project'], 'tutorial')
+
+
+class TestMyViewFailureCondition(BaseTest):
- def _callFUT(self, request):
- from tutorial.views import edit_page
- return edit_page(request)
-
- def test_it_notsubmitted(self):
- from tutorial.models import Page
- _registerRoutes(self.config)
- request = testing.DummyRequest()
- request.matchdict = {'pagename':'abc'}
- page = Page(name='abc', data='hello')
- self.session.add(page)
- info = self._callFUT(request)
- self.assertEqual(info['page'], page)
- self.assertEqual(info['save_url'],
- 'http://example.com/abc/edit_page')
-
- def test_it_submitted(self):
- from tutorial.models import Page
- _registerRoutes(self.config)
- request = testing.DummyRequest({'form.submitted':True,
- 'body':'Hello yo!'})
- request.matchdict = {'pagename':'abc'}
- page = Page(name='abc', data='hello')
- self.session.add(page)
- response = self._callFUT(request)
- self.assertEqual(response.location, 'http://example.com/abc')
- self.assertEqual(page.data, 'Hello yo!')
+ def test_failing_view(self):
+ from .views.default import my_view
+ info = my_view(dummy_request(self.session))
+ self.assertEqual(info.status_int, 500)
diff --git a/docs/tutorials/wiki2/src/views/tutorial/views.py b/docs/tutorials/wiki2/src/views/tutorial/views.py
deleted file mode 100644
index a3707dab5..000000000
--- a/docs/tutorials/wiki2/src/views/tutorial/views.py
+++ /dev/null
@@ -1,72 +0,0 @@
-import cgi
-import re
-from docutils.core import publish_parts
-
-from pyramid.httpexceptions import (
- HTTPFound,
- HTTPNotFound,
- )
-
-from pyramid.view import view_config
-
-from .models import (
- DBSession,
- Page,
- )
-
-# regular expression used to find WikiWords
-wikiwords = re.compile(r"\b([A-Z]\w+[A-Z]+\w+)")
-
-@view_config(route_name='view_wiki')
-def view_wiki(request):
- return HTTPFound(location = request.route_url('view_page',
- pagename='FrontPage'))
-
-@view_config(route_name='view_page', renderer='templates/view.pt')
-def view_page(request):
- pagename = request.matchdict['pagename']
- page = DBSession.query(Page).filter_by(name=pagename).first()
- if page is None:
- return HTTPNotFound('No such page')
-
- def check(match):
- word = match.group(1)
- exists = DBSession.query(Page).filter_by(name=word).all()
- if exists:
- view_url = request.route_url('view_page', pagename=word)
- return '<a href="%s">%s</a>' % (view_url, cgi.escape(word))
- else:
- add_url = request.route_url('add_page', pagename=word)
- return '<a href="%s">%s</a>' % (add_url, cgi.escape(word))
-
- content = publish_parts(page.data, writer_name='html')['html_body']
- content = wikiwords.sub(check, content)
- edit_url = request.route_url('edit_page', pagename=pagename)
- return dict(page=page, content=content, edit_url=edit_url)
-
-@view_config(route_name='add_page', renderer='templates/edit.pt')
-def add_page(request):
- pagename = request.matchdict['pagename']
- if 'form.submitted' in request.params:
- body = request.params['body']
- page = Page(name=pagename, data=body)
- DBSession.add(page)
- return HTTPFound(location = request.route_url('view_page',
- pagename=pagename))
- save_url = request.route_url('add_page', pagename=pagename)
- page = Page(name='', data='')
- return dict(page=page, save_url=save_url)
-
-@view_config(route_name='edit_page', renderer='templates/edit.pt')
-def edit_page(request):
- pagename = request.matchdict['pagename']
- page = DBSession.query(Page).filter_by(name=pagename).one()
- if 'form.submitted' in request.params:
- page.data = request.params['body']
- DBSession.add(page)
- return HTTPFound(location = request.route_url('view_page',
- pagename=pagename))
- return dict(
- page=page,
- save_url = request.route_url('edit_page', pagename=pagename),
- )