From 3214690b08e3c495ab64170e1430ece240853110 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Fri, 13 Nov 2015 02:30:32 -0800 Subject: update wiki2/src/views and wiki2/definingviews.rst --- docs/tutorials/wiki2/definingviews.rst | 12 +- docs/tutorials/wiki2/src/views/development.ini | 4 +- docs/tutorials/wiki2/src/views/production.ini | 14 +- docs/tutorials/wiki2/src/views/setup.py | 2 +- .../tutorials/wiki2/src/views/tutorial/__init__.py | 12 +- docs/tutorials/wiki2/src/views/tutorial/models.py | 25 --- .../src/views/tutorial/scripts/initializedb.py | 25 +-- .../wiki2/src/views/tutorial/templates/edit.pt | 69 -------- .../src/views/tutorial/templates/mytemplate.pt | 66 -------- .../wiki2/src/views/tutorial/templates/view.pt | 69 -------- docs/tutorials/wiki2/src/views/tutorial/tests.py | 175 ++++++--------------- docs/tutorials/wiki2/src/views/tutorial/views.py | 72 --------- 12 files changed, 83 insertions(+), 462 deletions(-) delete mode 100644 docs/tutorials/wiki2/src/views/tutorial/models.py delete mode 100644 docs/tutorials/wiki2/src/views/tutorial/templates/edit.pt delete mode 100644 docs/tutorials/wiki2/src/views/tutorial/templates/mytemplate.pt delete mode 100644 docs/tutorials/wiki2/src/views/tutorial/templates/view.pt delete mode 100644 docs/tutorials/wiki2/src/views/tutorial/views.py (limited to 'docs/tutorials/wiki2') diff --git a/docs/tutorials/wiki2/definingviews.rst b/docs/tutorials/wiki2/definingviews.rst index 0b495445a..8a96e433c 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,17 +60,17 @@ 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`` ===================================== -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 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 \n' + print('usage: %s [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 @@ - - - - - - - - - - - ${page.name} - Pyramid tutorial wiki (based on - TurboGears 20-Minute Wiki) - - - - - - - - - - - - -
-
-
-
- -
-
-
-

- Editing Page Name Goes - Here -

-

You can return to the - FrontPage. -

-
-
- -
-
- -
-
-
-
-
-
- -
-
-
- - - - - - - - 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 @@ - - - - - - - - - - - Alchemy Scaffold for The Pyramid Web Framework - - - - - - - - - - - - - -
-
-
-
- -
-
-
-

Pyramid Alchemy scaffold

-

Welcome to ${project}, an application generated by
the Pyramid Web Framework.

-
-
-
- -
- -
-
-
- - - - - - - - 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 @@ - - - - - - - - - - - ${page.name} - Pyramid tutorial wiki (based on - TurboGears 20-Minute Wiki) - - - - - - - - - - - - -
-
-
-
- -
-
-
-
- Page text goes here. -
-

- - Edit this page - -

-

- Viewing - Page Name Goes Here -

-

You can return to the - FrontPage. -

-
-
-
-
- -
-
-
- - - - - - - - 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'], - '
\n' - '

Hello ' - 'CruelWorld ' - '' - 'IDoExist' - '

\n
\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 '%s' % (view_url, cgi.escape(word)) - else: - add_url = request.route_url('add_page', pagename=word) - return '%s' % (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), - ) -- cgit v1.2.3 From 429529a09992554229ef7274bfc4f43394256105 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Fri, 13 Nov 2015 03:46:13 -0800 Subject: update wiki2/src/views and wiki2/definingviews.rst --- docs/tutorials/wiki2/definingviews.rst | 113 +++++++++++++++++---------------- 1 file changed, 58 insertions(+), 55 deletions(-) (limited to 'docs/tutorials/wiki2') diff --git a/docs/tutorials/wiki2/definingviews.rst b/docs/tutorials/wiki2/definingviews.rst index 8a96e433c..08fa8f16b 100644 --- a/docs/tutorials/wiki2/definingviews.rst +++ b/docs/tutorials/wiki2/definingviews.rst @@ -64,8 +64,8 @@ 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/default.py`` and edit it to look like the following: @@ -73,18 +73,19 @@ edit it to look like the following: .. 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 ">", 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 ">"). +- 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(':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. -- cgit v1.2.3