From a2b15855bee4893524609a941954c823bfbcec0d Mon Sep 17 00:00:00 2001 From: Paul Everitt Date: Tue, 8 Oct 2013 14:33:16 -0400 Subject: Small quick tutorial fixes post conference. --- docs/quick_tutorial/databases.rst | 11 +-- .../debugtoolbar/tutorial/__init__.py | 4 +- docs/quick_tutorial/ini.rst | 2 +- docs/quick_tutorial/jinja2.rst | 7 +- docs/quick_tutorial/jinja2/development.ini | 1 - docs/quick_tutorial/jinja2/tutorial/__init__.py | 1 + docs/quick_tutorial/more_view_classes.rst | 2 +- docs/quick_tutorial/requirements.rst | 2 +- docs/quick_tutorial/retail_forms/development.ini | 41 +++++++++ docs/quick_tutorial/retail_forms/setup.py | 15 ++++ .../retail_forms/tutorial/__init__.py | 13 +++ docs/quick_tutorial/retail_forms/tutorial/tests.py | 36 ++++++++ docs/quick_tutorial/retail_forms/tutorial/views.py | 96 ++++++++++++++++++++++ .../retail_forms/tutorial/wiki_view.pt | 19 +++++ .../retail_forms/tutorial/wikipage_addedit.pt | 37 +++++++++ .../retail_forms/tutorial/wikipage_view.pt | 17 ++++ docs/quick_tutorial/unit_testing.rst | 2 +- docs/quick_tutorial/views.rst | 2 +- 18 files changed, 286 insertions(+), 22 deletions(-) create mode 100644 docs/quick_tutorial/retail_forms/development.ini create mode 100644 docs/quick_tutorial/retail_forms/setup.py create mode 100644 docs/quick_tutorial/retail_forms/tutorial/__init__.py create mode 100644 docs/quick_tutorial/retail_forms/tutorial/tests.py create mode 100644 docs/quick_tutorial/retail_forms/tutorial/views.py create mode 100644 docs/quick_tutorial/retail_forms/tutorial/wiki_view.pt create mode 100644 docs/quick_tutorial/retail_forms/tutorial/wikipage_addedit.pt create mode 100644 docs/quick_tutorial/retail_forms/tutorial/wikipage_view.pt (limited to 'docs/quick_tutorial') diff --git a/docs/quick_tutorial/databases.rst b/docs/quick_tutorial/databases.rst index 93a02ffc7..20b3cd46d 100644 --- a/docs/quick_tutorial/databases.rst +++ b/docs/quick_tutorial/databases.rst @@ -39,15 +39,6 @@ Objectives Steps ===== -.. warning:: - - Your Python might not have SQLite bundled. If not, install it into - your virtual environment with: - - .. code-block:: bash - - $ $VENV/bin/easy_install sphinx pysqlite - #. We are going to use the forms step as our starting point: .. code-block:: bash @@ -97,7 +88,7 @@ Steps .. code-block:: bash - $ initialize_tutorial_db development.ini + $ $VENV/bin/initialize_tutorial_db development.ini 2013-09-06 15:54:08,050 INFO [sqlalchemy.engine.base.Engine][MainThread] PRAGMA table_info("wikipages") 2013-09-06 15:54:08,050 INFO [sqlalchemy.engine.base.Engine][MainThread] () 2013-09-06 15:54:08,051 INFO [sqlalchemy.engine.base.Engine][MainThread] diff --git a/docs/quick_tutorial/debugtoolbar/tutorial/__init__.py b/docs/quick_tutorial/debugtoolbar/tutorial/__init__.py index 2b4e84f30..0993b25be 100644 --- a/docs/quick_tutorial/debugtoolbar/tutorial/__init__.py +++ b/docs/quick_tutorial/debugtoolbar/tutorial/__init__.py @@ -3,11 +3,11 @@ from pyramid.response import Response def hello_world(request): - return Response('

Hello World!

') + return xResponse('

Hello World!

') def main(global_config, **settings): config = Configurator(settings=settings) config.add_route('hello', '/') config.add_view(hello_world, route_name='hello') - return config.make_wsgi_app() \ No newline at end of file + return config.make_wsgi_app() diff --git a/docs/quick_tutorial/ini.rst b/docs/quick_tutorial/ini.rst index 630b1faa5..618b8e5e8 100644 --- a/docs/quick_tutorial/ini.rst +++ b/docs/quick_tutorial/ini.rst @@ -46,7 +46,7 @@ Steps :linenos: #. We can now install our project, thus generating (or re-generating) an - "egg" at ``ini/tutorial.egg-info``: + "egg" at ``ini/tutorial.egg-info``: .. code-block:: bash diff --git a/docs/quick_tutorial/jinja2.rst b/docs/quick_tutorial/jinja2.rst index 40d941098..44d9f635b 100644 --- a/docs/quick_tutorial/jinja2.rst +++ b/docs/quick_tutorial/jinja2.rst @@ -29,11 +29,10 @@ Steps $ $VENV/bin/python setup.py develop $ $VENV/bin/easy_install pyramid_jinja2 -#. We need to add an item to ``pyramid.includes`` in - ``jinja2/development.ini``: +#. We need to include ``pyramid_jinja2`` in + ``jinja2/tutorial/__init__.py``: - .. literalinclude:: jinja2/development.ini - :language: ini + .. literalinclude:: jinja2/tutorial/__init__.py :linenos: #. Our ``jinja2/tutorial/views.py`` simply changes its ``renderer``: diff --git a/docs/quick_tutorial/jinja2/development.ini b/docs/quick_tutorial/jinja2/development.ini index c096fa936..62e0c5123 100644 --- a/docs/quick_tutorial/jinja2/development.ini +++ b/docs/quick_tutorial/jinja2/development.ini @@ -3,7 +3,6 @@ use = egg:tutorial pyramid.reload_templates = true pyramid.includes = pyramid_debugtoolbar - pyramid_jinja2 [server:main] use = egg:pyramid#wsgiref diff --git a/docs/quick_tutorial/jinja2/tutorial/__init__.py b/docs/quick_tutorial/jinja2/tutorial/__init__.py index 013d4538f..1f6783c06 100644 --- a/docs/quick_tutorial/jinja2/tutorial/__init__.py +++ b/docs/quick_tutorial/jinja2/tutorial/__init__.py @@ -3,6 +3,7 @@ from pyramid.config import Configurator def main(global_config, **settings): config = Configurator(settings=settings) + config.include('pyramid_jinja2') config.add_route('home', '/') config.add_route('hello', '/howdy') config.scan('.views') diff --git a/docs/quick_tutorial/more_view_classes.rst b/docs/quick_tutorial/more_view_classes.rst index 2792869ac..21b353b7c 100644 --- a/docs/quick_tutorial/more_view_classes.rst +++ b/docs/quick_tutorial/more_view_classes.rst @@ -166,7 +166,7 @@ Extra Credit #. The ``edit`` and ``delete`` views are both submitted to with ``POST``. Why does the ``edit`` view configuration not catch the - the ``POST`` used by ``delete``? + ``POST`` used by ``delete``? #. We used Python ``@property`` on ``full_name``. If we reference this many times in a template or view code, it would re-compute this diff --git a/docs/quick_tutorial/requirements.rst b/docs/quick_tutorial/requirements.rst index 40e818807..234e4aa0d 100644 --- a/docs/quick_tutorial/requirements.rst +++ b/docs/quick_tutorial/requirements.rst @@ -226,7 +226,7 @@ during this tutorial: # Mac and Linux $ $VENV/bin/easy_install nose webtest deform sqlalchemy \ pyramid_chameleon pyramid_debugtoolbar waitress \ - pyramid_jinja2 pyramid_tm zope.sqlalchemy pysqlite + pyramid_jinja2 pyramid_tm zope.sqlalchemy # Windows c:\> %VENV%\Scripts\easy_install nose webtest deform sqlalchemy pyramid_chameleon diff --git a/docs/quick_tutorial/retail_forms/development.ini b/docs/quick_tutorial/retail_forms/development.ini new file mode 100644 index 000000000..62e0c5123 --- /dev/null +++ b/docs/quick_tutorial/retail_forms/development.ini @@ -0,0 +1,41 @@ +[app:main] +use = egg:tutorial +pyramid.reload_templates = true +pyramid.includes = + pyramid_debugtoolbar + +[server:main] +use = egg:pyramid#wsgiref +host = 0.0.0.0 +port = 6543 + +# Begin logging configuration + +[loggers] +keys = root, tutorial + +[logger_tutorial] +level = DEBUG +handlers = +qualname = tutorial + +[handlers] +keys = console + +[formatters] +keys = generic + +[logger_root] +level = INFO +handlers = console + +[handler_console] +class = StreamHandler +args = (sys.stderr,) +level = NOTSET +formatter = generic + +[formatter_generic] +format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s + +# End logging configuration diff --git a/docs/quick_tutorial/retail_forms/setup.py b/docs/quick_tutorial/retail_forms/setup.py new file mode 100644 index 000000000..361ade013 --- /dev/null +++ b/docs/quick_tutorial/retail_forms/setup.py @@ -0,0 +1,15 @@ +from setuptools import setup + +requires = [ + 'pyramid', + 'pyramid_chameleon', + 'deform' +] + +setup(name='tutorial', + install_requires=requires, + entry_points="""\ + [paste.app_factory] + main = tutorial:main + """, +) \ No newline at end of file diff --git a/docs/quick_tutorial/retail_forms/tutorial/__init__.py b/docs/quick_tutorial/retail_forms/tutorial/__init__.py new file mode 100644 index 000000000..dff7457cf --- /dev/null +++ b/docs/quick_tutorial/retail_forms/tutorial/__init__.py @@ -0,0 +1,13 @@ +from pyramid.config import Configurator + + +def main(global_config, **settings): + config = Configurator(settings=settings) + config.include('pyramid_chameleon') + config.add_route('wiki_view', '/') + config.add_route('wikipage_add', '/add') + config.add_route('wikipage_view', '/{uid}') + config.add_route('wikipage_edit', '/{uid}/edit') + config.add_static_view('deform_static', 'deform:static/') + config.scan('.views') + return config.make_wsgi_app() diff --git a/docs/quick_tutorial/retail_forms/tutorial/tests.py b/docs/quick_tutorial/retail_forms/tutorial/tests.py new file mode 100644 index 000000000..5a2c40904 --- /dev/null +++ b/docs/quick_tutorial/retail_forms/tutorial/tests.py @@ -0,0 +1,36 @@ +import unittest + +from pyramid import testing + + +class TutorialViewTests(unittest.TestCase): + def setUp(self): + self.config = testing.setUp() + + def tearDown(self): + testing.tearDown() + + def test_home(self): + from .views import WikiViews + + request = testing.DummyRequest() + inst = WikiViews(request) + response = inst.wiki_view() + self.assertEqual(len(response['pages']), 3) + + +class TutorialFunctionalTests(unittest.TestCase): + def setUp(self): + from tutorial import main + + app = main({}) + from webtest import TestApp + + self.testapp = TestApp(app) + + def tearDown(self): + testing.tearDown() + + def test_home(self): + res = self.testapp.get('/', status=200) + self.assertIn(b'Wiki: View', res.body) diff --git a/docs/quick_tutorial/retail_forms/tutorial/views.py b/docs/quick_tutorial/retail_forms/tutorial/views.py new file mode 100644 index 000000000..2737ebdc4 --- /dev/null +++ b/docs/quick_tutorial/retail_forms/tutorial/views.py @@ -0,0 +1,96 @@ +import colander +import deform.widget + +from pyramid.httpexceptions import HTTPFound +from pyramid.view import view_config + +pages = { + '100': dict(uid='100', title='Page 100', body='100'), + '101': dict(uid='101', title='Page 101', body='101'), + '102': dict(uid='102', title='Page 102', body='102') +} + +class WikiPage(colander.MappingSchema): + title = colander.SchemaNode(colander.String()) + body = colander.SchemaNode( + colander.String(), + widget=deform.widget.RichTextWidget() + ) + + +class WikiViews(object): + def __init__(self, request): + self.request = request + + @property + def wiki_form(self): + schema = WikiPage() + return deform.Form(schema, buttons=('submit',)) + + @property + def reqts(self): + return self.wiki_form.get_widget_resources() + + @view_config(route_name='wiki_view', renderer='wiki_view.pt') + def wiki_view(self): + return dict(pages=pages.values()) + + @view_config(route_name='wikipage_add', + renderer='wikipage_addedit.pt') + def wikipage_add(self): + form = self.wiki_form + + if 'submit' in self.request.params: + controls = self.request.POST.items() + try: + appstruct = self.wiki_form.validate(controls) + except deform.ValidationFailure as e: + # Form is NOT valid + return dict(form=e.render()) + + # Form is valid, make a new identifier and add to list + last_uid = int(sorted(pages.keys())[-1]) + new_uid = str(last_uid + 1) + pages[new_uid] = dict( + uid=new_uid, title=appstruct['title'], + body=appstruct['body'] + ) + + # Now visit new page + url = self.request.route_url('wikipage_view', uid=new_uid) + return HTTPFound(url) + + return dict(form=form) + + @view_config(route_name='wikipage_view', renderer='wikipage_view.pt') + def wikipage_view(self): + uid = self.request.matchdict['uid'] + page = pages[uid] + return dict(page=page) + + @view_config(route_name='wikipage_edit', + renderer='wikipage_addedit.pt') + def wikipage_edit(self): + uid = self.request.matchdict['uid'] + page = pages[uid] + + wiki_form = self.wiki_form + + if 'submit' in self.request.params: + controls = self.request.POST.items() + try: + appstruct = wiki_form.validate(controls) + except deform.ValidationFailure as e: + return dict(page=page, form=e.render()) + + # Change the content and redirect to the view + page['title'] = appstruct['title'] + page['body'] = appstruct['body'] + + url = self.request.route_url('wikipage_view', + uid=page['uid']) + return HTTPFound(url) + + form = wiki_form.render(page) + + return dict(page=page, form=form) \ No newline at end of file diff --git a/docs/quick_tutorial/retail_forms/tutorial/wiki_view.pt b/docs/quick_tutorial/retail_forms/tutorial/wiki_view.pt new file mode 100644 index 000000000..9e3afe495 --- /dev/null +++ b/docs/quick_tutorial/retail_forms/tutorial/wiki_view.pt @@ -0,0 +1,19 @@ + + + + Wiki: View + + +

Wiki

+ +Add + WikiPage + + + \ No newline at end of file diff --git a/docs/quick_tutorial/retail_forms/tutorial/wikipage_addedit.pt b/docs/quick_tutorial/retail_forms/tutorial/wikipage_addedit.pt new file mode 100644 index 000000000..586f4c44b --- /dev/null +++ b/docs/quick_tutorial/retail_forms/tutorial/wikipage_addedit.pt @@ -0,0 +1,37 @@ + + + + WikiPage: Add/Edit + + + + + + + + +

Wiki

+ +
+
+ ${structure:field.title} + * +
+
+ ${structure:field.serialize()} +
+ +
+ + + + diff --git a/docs/quick_tutorial/retail_forms/tutorial/wikipage_view.pt b/docs/quick_tutorial/retail_forms/tutorial/wikipage_view.pt new file mode 100644 index 000000000..cb9ff526e --- /dev/null +++ b/docs/quick_tutorial/retail_forms/tutorial/wikipage_view.pt @@ -0,0 +1,17 @@ + + + + WikiPage: View + + + + Up + | + + Edit + + +

${page.title}

+

${structure: page.body}

+ + \ No newline at end of file diff --git a/docs/quick_tutorial/unit_testing.rst b/docs/quick_tutorial/unit_testing.rst index 73b33c588..ed33f62d7 100644 --- a/docs/quick_tutorial/unit_testing.rst +++ b/docs/quick_tutorial/unit_testing.rst @@ -77,7 +77,7 @@ some ``pyramid.testing`` helpers which we use in the test setup and teardown. Our one test imports the view, makes a dummy request, and sees if the view returns what we expected. -The ``tests.HelloWorldViewTests.test_hello_world`` test is a small +The ``tests.TutorialViewTests.test_hello_world`` test is a small example of a unit test. First, we import the view inside each test. Why not import at the top, like in normal Python code? Because imports can cause effects that break a test. We'd like our tests to be in *units*, diff --git a/docs/quick_tutorial/views.rst b/docs/quick_tutorial/views.rst index 15785e902..529bba0a4 100644 --- a/docs/quick_tutorial/views.rst +++ b/docs/quick_tutorial/views.rst @@ -42,7 +42,7 @@ Steps .. code-block:: bash - $ cd ..; cp -r function_testing views; cd views + $ cd ..; cp -r functional_testing views; cd views $ $VENV/bin/python setup.py develop #. Our ``views/tutorial/__init__.py`` gets a lot shorter: -- cgit v1.2.3