summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorSteve Piercy <web@stevepiercy.com>2015-11-12 00:46:11 -0800
committerSteve Piercy <web@stevepiercy.com>2015-11-12 00:46:11 -0800
commit16a490fa4c44776d9a22b8a7ddc19a23702cb7ee (patch)
tree2e2bcac026852f2e681955720a6bb53ee304efde /docs
parent2aba031a8ef6fd7933b1d3f382303bc67a7c2acb (diff)
parent0409cf178d4c0fa9a0d3b0858ab2294935b23609 (diff)
downloadpyramid-16a490fa4c44776d9a22b8a7ddc19a23702cb7ee.tar.gz
pyramid-16a490fa4c44776d9a22b8a7ddc19a23702cb7ee.tar.bz2
pyramid-16a490fa4c44776d9a22b8a7ddc19a23702cb7ee.zip
Merge pull request #2112 from stevepiercy/feature/alchemy-scaffold-update
Finish work on basiclayout.rst and its src at wiki2/src/basiclayout/
Diffstat (limited to 'docs')
-rw-r--r--docs/tutorials/wiki2/basiclayout.rst147
-rw-r--r--docs/tutorials/wiki2/src/basiclayout/setup.py2
-rw-r--r--docs/tutorials/wiki2/src/basiclayout/tutorial/models.py27
-rw-r--r--docs/tutorials/wiki2/src/basiclayout/tutorial/models/__init__.py7
-rw-r--r--docs/tutorials/wiki2/src/basiclayout/tutorial/models/meta.py46
-rw-r--r--docs/tutorials/wiki2/src/basiclayout/tutorial/models/mymodel.py17
-rw-r--r--docs/tutorials/wiki2/src/basiclayout/tutorial/scripts/initializedb.py30
-rw-r--r--docs/tutorials/wiki2/src/basiclayout/tutorial/static/theme.min.css2
-rw-r--r--docs/tutorials/wiki2/src/basiclayout/tutorial/templates/layout.jinja2 (renamed from docs/tutorials/wiki2/src/basiclayout/tutorial/templates/mytemplate.pt)18
-rw-r--r--docs/tutorials/wiki2/src/basiclayout/tutorial/templates/mytemplate.jinja28
-rw-r--r--docs/tutorials/wiki2/src/basiclayout/tutorial/tests.py68
-rw-r--r--docs/tutorials/wiki2/src/basiclayout/tutorial/views/__init__.py0
-rw-r--r--docs/tutorials/wiki2/src/basiclayout/tutorial/views/default.py (renamed from docs/tutorials/wiki2/src/basiclayout/tutorial/views.py)18
13 files changed, 243 insertions, 147 deletions
diff --git a/docs/tutorials/wiki2/basiclayout.rst b/docs/tutorials/wiki2/basiclayout.rst
index 8a1dbf3f8..5d9b62eea 100644
--- a/docs/tutorials/wiki2/basiclayout.rst
+++ b/docs/tutorials/wiki2/basiclayout.rst
@@ -113,20 +113,22 @@ Finally ``main`` is finished configuring things, so it uses the
:term:`WSGI` application:
.. literalinclude:: src/basiclayout/tutorial/__init__.py
- :lines: 21
+ :lines: 13
:language: py
-View declarations via ``views.py``
-----------------------------------
+
+View declarations via the ``views`` package
+-------------------------------------------
The main function of a web framework is mapping each URL pattern to code (a
:term:`view callable`) that is executed when the requested URL matches the
corresponding :term:`route`. Our application uses the
:meth:`pyramid.view.view_config` decorator to perform this mapping.
-Open ``tutorial/tutorial/views.py``. It should already contain the following:
+Open ``tutorial/tutorial/views/default.py`` in the ``views`` package. It
+should already contain the following:
- .. literalinclude:: src/basiclayout/tutorial/views.py
+ .. literalinclude:: src/basiclayout/tutorial/views/default.py
:linenos:
:language: py
@@ -135,13 +137,13 @@ function it decorates (``my_view``) with a :term:`view configuration`,
consisting of:
* a ``route_name`` (``home``)
- * a ``renderer``, which is a template from the ``templates`` subdirectory
- of the package.
+ * a ``renderer``, which is a template from the ``templates`` subdirectory of
+ the package.
When the pattern associated with the ``home`` view is matched during a request,
-``my_view()`` will be executed. ``my_view()`` returns a dictionary; the
-renderer will use the ``templates/mytemplate.pt`` template to create a response
-based on the values in the dictionary.
+``my_view()`` will be executed. ``my_view()`` returns a dictionary; the
+renderer will use the ``templates/mytemplate.jinja2`` template to create a
+response based on the values in the dictionary.
Note that ``my_view()`` accepts a single argument named ``request``. This is
the standard call signature for a Pyramid :term:`view callable`.
@@ -154,100 +156,105 @@ application. Without being processed by ``scan``, the decorator effectively
does nothing. ``@view_config`` is inert without being detected via a
:term:`scan`.
-The sample ``my_view()`` created by the scaffold uses a ``try:`` and ``except:``
-clause to detect if there is a problem accessing the project database and
-provide an alternate error response. That response will include the text
-shown at the end of the file, which will be displayed in the browser to
-inform the user about possible actions to take to solve the problem.
+The sample ``my_view()`` created by the scaffold uses a ``try:`` and
+``except:`` clause to detect if there is a problem accessing the project
+database and provide an alternate error response. That response will include
+the text shown at the end of the file, which will be displayed in the browser
+to inform the user about possible actions to take to solve the problem.
-Content Models with ``models.py``
----------------------------------
+Content models with the ``models`` package
+------------------------------------------
-.. START moved from Application configuration with ``__init__.py``. This
- section is a WIP, and needs to be updated using the new models package.
+In a SQLAlchemy-based application, a *model* object is an object composed by
+querying the SQL database. The ``models`` package is where the ``alchemy``
+scaffold put the classes that implement our models.
-The main function first creates a :term:`SQLAlchemy` database engine using
-:func:`sqlalchemy.engine_from_config` from the ``sqlalchemy.`` prefixed
-settings in the ``development.ini`` file's ``[app:main]`` section.
-This will be a URI (something like ``sqlite://``):
+First, open ``tutorial/tutorial/models/__init__.py``, which should already
+contain the following:
- .. literalinclude:: src/basiclayout/tutorial/__init__.py
- :lines: 13
+ .. literalinclude:: src/basiclayout/tutorial/models/__init__.py
+ :linenos:
:language: py
-``main`` then initializes our SQLAlchemy session object, passing it the
-engine:
+Our ``__init__.py`` will perform some imports to support later code, then calls
+the function :func:`sqlalchemy.orm.configure_mappers`.
- .. literalinclude:: src/basiclayout/tutorial/__init__.py
- :lines: 14
+Next open ``tutorial/tutorial/models/meta.py``, which should already contain
+the following:
+
+ .. literalinclude:: src/basiclayout/tutorial/models/meta.py
+ :linenos:
:language: py
-``main`` subsequently initializes our SQLAlchemy declarative ``Base`` object,
-assigning the engine we created to the ``bind`` attribute of it's
-``metadata`` object. This allows table definitions done imperatively
-(instead of declaratively, via a class statement) to work. We won't use any
-such tables in our application, but if you add one later, long after you've
-forgotten about this tutorial, you won't be left scratching your head when it
-doesn't work.
+``meta.py`` contains imports that are used to support later code. We create a
+dictionary ``NAMING_CONVENTION`` as well.
- .. literalinclude:: src/basiclayout/tutorial/__init__.py
- :lines: 15
+ .. literalinclude:: src/basiclayout/tutorial/models/meta.py
+ :end-before: metadata
+ :linenos:
:language: py
-.. END moved from Application configuration with ``__init__.py``
+Next we create a ``metadata`` object from the class
+:class:`sqlalchemy.schema.MetaData`, using ``NAMING_CONVENTION`` as the value
+for the ``naming_convention`` argument. We also need to create a declarative
+``Base`` object to use as a base class for our model. Then our model classes
+will inherit from the ``Base`` class so they can be associated with our
+particular database connection.
-In a SQLAlchemy-based application, a *model* object is an object composed by
-querying the SQL database. The ``models.py`` file is where the ``alchemy``
-scaffold put the classes that implement our models.
+ .. literalinclude:: src/basiclayout/tutorial/models/meta.py
+ :lines: 15-16
+ :lineno-start: 15
+ :linenos:
+ :language: py
-Open ``tutorial/tutorial/models.py``. It should already contain the following:
+Next we define several functions, the first of which is ``includeme``, which
+configures various database settings by calling subsequently defined functions.
- .. literalinclude:: src/basiclayout/tutorial/models.py
+ .. literalinclude:: src/basiclayout/tutorial/models/meta.py
+ :pyobject: includeme
:linenos:
:language: py
-Let's examine this in detail. First, we need some imports to support later code:
+The function ``get_session`` registers a database session with a transaction
+manager, and returns a ``dbsession`` object. With the transaction manager, our
+application will automatically issue a transaction commit after every request
+unless an exception is raised, in which case the transaction will be aborted.
- .. literalinclude:: src/basiclayout/tutorial/models.py
- :end-before: DBSession
+ .. literalinclude:: src/basiclayout/tutorial/models/meta.py
+ :pyobject: get_session
:linenos:
:language: py
-Next we set up a SQLAlchemy ``DBSession`` object:
+The ``get_engine`` function creates an :term:`SQLAlchemy` database engine using
+:func:`sqlalchemy.engine_from_config` from the ``sqlalchemy.``-prefixed
+settings in the ``development.ini`` file's ``[app:main]`` section, which is a
+URI, something like ``sqlite://``.
- .. literalinclude:: src/basiclayout/tutorial/models.py
- :lines: 17
+ .. literalinclude:: src/basiclayout/tutorial/models/meta.py
+ :pyobject: get_engine
+ :linenos:
:language: py
-``scoped_session`` and ``sessionmaker`` are standard SQLAlchemy helpers.
-``scoped_session`` allows us to access our database connection globally.
-``sessionmaker`` creates a database session object. We pass to
-``sessionmaker`` the ``extension=ZopeTransactionExtension()`` extension
-option in order to allow the system to automatically manage database
-transactions. With ``ZopeTransactionExtension`` activated, our application
-will automatically issue a transaction commit after every request unless an
-exception is raised, in which case the transaction will be aborted.
-
-We also need to create a declarative ``Base`` object to use as a
-base class for our model:
+The function ``get_dbmaker`` accepts an :term:`SQLAlchemy` database engine,
+and creates a database session object ``dbmaker`` from the :term:`SQLAlchemy`
+class :class:`sqlalchemy.orm.session.sessionmaker`, which is then used for
+creating a session with the database engine.
- .. literalinclude:: src/basiclayout/tutorial/models.py
- :lines: 17
+ .. literalinclude:: src/basiclayout/tutorial/models/meta.py
+ :pyobject: get_dbmaker
+ :linenos:
:language: py
-Our model classes will inherit from this ``Base`` class so they can be
-associated with our particular database connection.
-
-To give a simple example of a model class, we define one named ``MyModel``:
+To give a simple example of a model class, we define one named ``MyModel``:
- .. literalinclude:: src/basiclayout/tutorial/models.py
+ .. literalinclude:: src/basiclayout/tutorial/models/mymodel.py
:pyobject: MyModel
:linenos:
:language: py
Our example model does not require an ``__init__`` method because SQLAlchemy
-supplies for us a default constructor if one is not already present,
-which accepts keyword arguments of the same name as that of the mapped attributes.
+supplies for us a default constructor if one is not already present, which
+accepts keyword arguments of the same name as that of the mapped attributes.
.. note:: Example usage of MyModel:
diff --git a/docs/tutorials/wiki2/src/basiclayout/setup.py b/docs/tutorials/wiki2/src/basiclayout/setup.py
index 15e7e5923..eb771010f 100644
--- a/docs/tutorials/wiki2/src/basiclayout/setup.py
+++ b/docs/tutorials/wiki2/src/basiclayout/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/basiclayout/tutorial/models.py b/docs/tutorials/wiki2/src/basiclayout/tutorial/models.py
deleted file mode 100644
index 11ddccadb..000000000
--- a/docs/tutorials/wiki2/src/basiclayout/tutorial/models.py
+++ /dev/null
@@ -1,27 +0,0 @@
-from sqlalchemy import (
- Column,
- Integer,
- Text,
- Index,
- )
-
-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 MyModel(Base):
- __tablename__ = 'models'
- id = Column(Integer, primary_key=True)
- name = Column(Text, unique=True)
- value = Column(Integer)
-
-Index('my_index', MyModel.name, unique=True, mysql_length=255)
diff --git a/docs/tutorials/wiki2/src/basiclayout/tutorial/models/__init__.py b/docs/tutorials/wiki2/src/basiclayout/tutorial/models/__init__.py
new file mode 100644
index 000000000..6ffc10a78
--- /dev/null
+++ b/docs/tutorials/wiki2/src/basiclayout/tutorial/models/__init__.py
@@ -0,0 +1,7 @@
+from sqlalchemy.orm import configure_mappers
+# import all models classes here for sqlalchemy mappers
+# to pick up
+from .mymodel import MyModel # flake8: noqa
+
+# run configure mappers to ensure we avoid any race conditions
+configure_mappers()
diff --git a/docs/tutorials/wiki2/src/basiclayout/tutorial/models/meta.py b/docs/tutorials/wiki2/src/basiclayout/tutorial/models/meta.py
new file mode 100644
index 000000000..b72b45f9f
--- /dev/null
+++ b/docs/tutorials/wiki2/src/basiclayout/tutorial/models/meta.py
@@ -0,0 +1,46 @@
+from sqlalchemy import engine_from_config
+from sqlalchemy.ext.declarative import declarative_base
+from sqlalchemy.orm import sessionmaker
+from sqlalchemy.schema import MetaData
+import zope.sqlalchemy
+
+NAMING_CONVENTION = {
+ "ix": 'ix_%(column_0_label)s',
+ "uq": "uq_%(table_name)s_%(column_0_name)s",
+ "ck": "ck_%(table_name)s_%(constraint_name)s",
+ "fk": "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s",
+ "pk": "pk_%(table_name)s"
+}
+
+metadata = MetaData(naming_convention=NAMING_CONVENTION)
+Base = declarative_base(metadata=metadata)
+
+
+def includeme(config):
+ settings = config.get_settings()
+ dbmaker = get_dbmaker(get_engine(settings))
+
+ config.add_request_method(
+ lambda r: get_session(r.tm, dbmaker),
+ 'dbsession',
+ reify=True
+ )
+
+ config.include('pyramid_tm')
+
+
+def get_session(transaction_manager, dbmaker):
+ dbsession = dbmaker()
+ zope.sqlalchemy.register(dbsession,
+ transaction_manager=transaction_manager)
+ return dbsession
+
+
+def get_engine(settings, prefix='sqlalchemy.'):
+ return engine_from_config(settings, prefix)
+
+
+def get_dbmaker(engine):
+ dbmaker = sessionmaker()
+ dbmaker.configure(bind=engine)
+ return dbmaker
diff --git a/docs/tutorials/wiki2/src/basiclayout/tutorial/models/mymodel.py b/docs/tutorials/wiki2/src/basiclayout/tutorial/models/mymodel.py
new file mode 100644
index 000000000..5a2b5890c
--- /dev/null
+++ b/docs/tutorials/wiki2/src/basiclayout/tutorial/models/mymodel.py
@@ -0,0 +1,17 @@
+from .meta import Base
+from sqlalchemy import (
+ Column,
+ Index,
+ Integer,
+ Text,
+)
+
+
+class MyModel(Base):
+ __tablename__ = 'models'
+ id = Column(Integer, primary_key=True)
+ name = Column(Text)
+ value = Column(Integer)
+
+
+Index('my_index', MyModel.name, unique=True, mysql_length=255)
diff --git a/docs/tutorials/wiki2/src/basiclayout/tutorial/scripts/initializedb.py b/docs/tutorials/wiki2/src/basiclayout/tutorial/scripts/initializedb.py
index 66feb3008..f0d09729e 100644
--- a/docs/tutorials/wiki2/src/basiclayout/tutorial/scripts/initializedb.py
+++ b/docs/tutorials/wiki2/src/basiclayout/tutorial/scripts/initializedb.py
@@ -2,36 +2,44 @@ import os
import sys
import transaction
-from sqlalchemy import engine_from_config
-
from pyramid.paster import (
get_appsettings,
setup_logging,
)
-from ..models import (
- DBSession,
- MyModel,
+from pyramid.scripts.common import parse_vars
+
+from ..models.meta import (
Base,
+ get_session,
+ get_engine,
+ get_dbmaker,
)
+from ..models.mymodel import MyModel
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]
+ options = parse_vars(argv[2:])
setup_logging(config_uri)
- settings = get_appsettings(config_uri)
- engine = engine_from_config(settings, 'sqlalchemy.')
- DBSession.configure(bind=engine)
+ settings = get_appsettings(config_uri, options=options)
+
+ engine = get_engine(settings)
+ dbmaker = get_dbmaker(engine)
+
+ dbsession = get_session(transaction.manager, dbmaker)
+
Base.metadata.create_all(engine)
+
with transaction.manager:
model = MyModel(name='one', value=1)
- DBSession.add(model)
+ dbsession.add(model)
diff --git a/docs/tutorials/wiki2/src/basiclayout/tutorial/static/theme.min.css b/docs/tutorials/wiki2/src/basiclayout/tutorial/static/theme.min.css
index 2f924bcc5..0d25de5b6 100644
--- a/docs/tutorials/wiki2/src/basiclayout/tutorial/static/theme.min.css
+++ b/docs/tutorials/wiki2/src/basiclayout/tutorial/static/theme.min.css
@@ -1 +1 @@
-@import url(//fonts.googleapis.com/css?family=Open+Sans:300,400,600,700);body{font-family:"Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif;font-weight:300;color:#fff;background:#bc2131}h1,h2,h3,h4,h5,h6{font-family:"Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif;font-weight:300}p{font-weight:300}.font-normal{font-weight:400}.font-semi-bold{font-weight:600}.font-bold{font-weight:700}.starter-template{margin-top:250px}.starter-template .content{margin-left:10px}.starter-template .content h1{margin-top:10px;font-size:60px}.starter-template .content h1 .smaller{font-size:40px;color:#f2b7bd}.starter-template .content .lead{font-size:25px;color:#f2b7bd}.starter-template .content .lead .font-normal{color:#fff}.starter-template .links{float:right;right:0;margin-top:125px}.starter-template .links ul{display:block;padding:0;margin:0}.starter-template .links ul li{list-style:none;display:inline;margin:0 10px}.starter-template .links ul li:first-child{margin-left:0}.starter-template .links ul li:last-child{margin-right:0}.starter-template .links ul li.current-version{color:#f2b7bd;font-weight:400}.starter-template .links ul li a{color:#fff}.starter-template .links ul li a:hover{text-decoration:underline}.starter-template .links ul li .icon-muted{color:#eb8b95;margin-right:5px}.starter-template .links ul li:hover .icon-muted{color:#fff}.starter-template .copyright{margin-top:10px;font-size:.9em;color:#f2b7bd;text-transform:lowercase;float:right;right:0}@media (max-width:1199px){.starter-template .content h1{font-size:45px}.starter-template .content h1 .smaller{font-size:30px}.starter-template .content .lead{font-size:20px}}@media (max-width:991px){.starter-template{margin-top:0}.starter-template .logo{margin:40px auto}.starter-template .content{margin-left:0;text-align:center}.starter-template .content h1{margin-bottom:20px}.starter-template .links{float:none;text-align:center;margin-top:60px}.starter-template .copyright{float:none;text-align:center}}@media (max-width:767px){.starter-template .content h1 .smaller{font-size:25px;display:block}.starter-template .content .lead{font-size:16px}.starter-template .links{margin-top:40px}.starter-template .links ul li{display:block;margin:0}.starter-template .links ul li .icon-muted{display:none}.starter-template .copyright{margin-top:20px}} \ No newline at end of file
+@import url(//fonts.googleapis.com/css?family=Open+Sans:300,400,600,700);body{font-family:"Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif;font-weight:300;color:#fff;background:#bc2131}h1,h2,h3,h4,h5,h6{font-family:"Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif;font-weight:300}p{font-weight:300}.font-normal{font-weight:400}.font-semi-bold{font-weight:600}.font-bold{font-weight:700}.starter-template{margin-top:250px}.starter-template .content{margin-left:10px}.starter-template .content h1{margin-top:10px;font-size:60px}.starter-template .content h1 .smaller{font-size:40px;color:#f2b7bd}.starter-template .content .lead{font-size:25px;color:#f2b7bd}.starter-template .content .lead .font-normal{color:#fff}.starter-template .links{float:right;right:0;margin-top:125px}.starter-template .links ul{display:block;padding:0;margin:0}.starter-template .links ul li{list-style:none;display:inline;margin:0 10px}.starter-template .links ul li:first-child{margin-left:0}.starter-template .links ul li:last-child{margin-right:0}.starter-template .links ul li.current-version{color:#f2b7bd;font-weight:400}.starter-template .links ul li a,a{color:#f2b7bd;text-decoration:underline}.starter-template .links ul li a:hover,a:hover{color:#fff;text-decoration:underline}.starter-template .links ul li .icon-muted{color:#eb8b95;margin-right:5px}.starter-template .links ul li:hover .icon-muted{color:#fff}.starter-template .copyright{margin-top:10px;font-size:.9em;color:#f2b7bd;text-transform:lowercase;float:right;right:0}@media (max-width:1199px){.starter-template .content h1{font-size:45px}.starter-template .content h1 .smaller{font-size:30px}.starter-template .content .lead{font-size:20px}}@media (max-width:991px){.starter-template{margin-top:0}.starter-template .logo{margin:40px auto}.starter-template .content{margin-left:0;text-align:center}.starter-template .content h1{margin-bottom:20px}.starter-template .links{float:none;text-align:center;margin-top:60px}.starter-template .copyright{float:none;text-align:center}}@media (max-width:767px){.starter-template .content h1 .smaller{font-size:25px;display:block}.starter-template .content .lead{font-size:16px}.starter-template .links{margin-top:40px}.starter-template .links ul li{display:block;margin:0}.starter-template .links ul li .icon-muted{display:none}.starter-template .copyright{margin-top:20px}}
diff --git a/docs/tutorials/wiki2/src/basiclayout/tutorial/templates/mytemplate.pt b/docs/tutorials/wiki2/src/basiclayout/tutorial/templates/layout.jinja2
index c9b0cec21..ff624c65b 100644
--- a/docs/tutorials/wiki2/src/basiclayout/tutorial/templates/mytemplate.pt
+++ b/docs/tutorials/wiki2/src/basiclayout/tutorial/templates/layout.jinja2
@@ -1,12 +1,12 @@
<!DOCTYPE html>
-<html lang="${request.locale_name}">
+<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')}">
+ <link rel="shortcut icon" href="{{request.static_url('tutorial:static/pyramid-16x16.png')}}">
<title>Alchemy Scaffold for The Pyramid Web Framework</title>
@@ -14,7 +14,7 @@
<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">
+ <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]>
@@ -29,19 +29,19 @@
<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">
+ <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>
+ {% block content %}
+ <p>No content</p>
+ {% endblock content %}
</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 class="current-version">Generated by v1.7.dev0</li>
+ <li><i class="glyphicon glyphicon-bookmark icon-muted"></i><a href="http://docs.pylonsproject.org/projects/pyramid/en/1.7-branch/">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>
diff --git a/docs/tutorials/wiki2/src/basiclayout/tutorial/templates/mytemplate.jinja2 b/docs/tutorials/wiki2/src/basiclayout/tutorial/templates/mytemplate.jinja2
new file mode 100644
index 000000000..bb622bf5a
--- /dev/null
+++ b/docs/tutorials/wiki2/src/basiclayout/tutorial/templates/mytemplate.jinja2
@@ -0,0 +1,8 @@
+{% extends "layout.jinja2" %}
+
+{% block content %}
+<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 1.7.dev0</span>.</p>
+</div>
+{% endblock content %}
diff --git a/docs/tutorials/wiki2/src/basiclayout/tutorial/tests.py b/docs/tutorials/wiki2/src/basiclayout/tutorial/tests.py
index 57a775e0a..b947e3bb1 100644
--- a/docs/tutorials/wiki2/src/basiclayout/tutorial/tests.py
+++ b/docs/tutorials/wiki2/src/basiclayout/tutorial/tests.py
@@ -3,31 +3,63 @@ import transaction
from pyramid import testing
-from .models import DBSession
+def dummy_request(dbsession):
+ return testing.DummyRequest(dbsession=dbsession)
-class TestMyView(unittest.TestCase):
+
+class BaseTest(unittest.TestCase):
def setUp(self):
- self.config = testing.setUp()
- from sqlalchemy import create_engine
- engine = create_engine('sqlite://')
- from .models import (
- Base,
- MyModel,
+ self.config = testing.setUp(settings={
+ 'sqlalchemy.url': 'sqlite:///:memory:'
+ })
+ self.config.include('.models.meta')
+ settings = self.config.get_settings()
+
+ from .models.meta import (
+ get_session,
+ get_engine,
+ get_dbmaker,
)
- DBSession.configure(bind=engine)
- Base.metadata.create_all(engine)
- with transaction.manager:
- model = MyModel(name='one', value=55)
- DBSession.add(model)
+
+ self.engine = get_engine(settings)
+ dbmaker = get_dbmaker(self.engine)
+
+ self.session = get_session(transaction.manager, dbmaker)
+
+ def init_database(self):
+ from .models.meta import Base
+ Base.metadata.create_all(self.engine)
def tearDown(self):
- DBSession.remove()
+ from .models.meta import Base
+
testing.tearDown()
+ transaction.abort()
+ Base.metadata.create_all(self.engine)
+
+
+class TestMyViewSuccessCondition(BaseTest):
- def test_it(self):
- from .views import my_view
- request = testing.DummyRequest()
- info = my_view(request)
+ def setUp(self):
+ super(TestMyViewSuccessCondition, self).setUp()
+ self.init_database()
+
+ 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 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/basiclayout/tutorial/views/__init__.py b/docs/tutorials/wiki2/src/basiclayout/tutorial/views/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/docs/tutorials/wiki2/src/basiclayout/tutorial/views/__init__.py
diff --git a/docs/tutorials/wiki2/src/basiclayout/tutorial/views.py b/docs/tutorials/wiki2/src/basiclayout/tutorial/views/default.py
index 4cfcae4af..13ad8793c 100644
--- a/docs/tutorials/wiki2/src/basiclayout/tutorial/views.py
+++ b/docs/tutorials/wiki2/src/basiclayout/tutorial/views/default.py
@@ -3,26 +3,25 @@ from pyramid.view import view_config
from sqlalchemy.exc import DBAPIError
-from .models import (
- DBSession,
- MyModel,
- )
+from ..models.mymodel import MyModel
-@view_config(route_name='home', renderer='templates/mytemplate.pt')
+@view_config(route_name='home', renderer='../templates/mytemplate.jinja2')
def my_view(request):
try:
- one = DBSession.query(MyModel).filter(MyModel.name == 'one').first()
+ query = request.dbsession.query(MyModel)
+ one = query.filter(MyModel.name == 'one').first()
except DBAPIError:
- return Response(conn_err_msg, content_type='text/plain', status_int=500)
+ return Response(db_err_msg, content_type='text/plain', status_int=500)
return {'one': one, 'project': 'tutorial'}
-conn_err_msg = """\
+
+db_err_msg = """\
Pyramid is having a problem using your SQL database. The problem
might be caused by one of the following things:
1. You may need to run the "initialize_tutorial_db" script
- to initialize your database tables. Check your virtual
+ to initialize your database tables. Check your virtual
environment's "bin" directory for this script and try to run it.
2. Your database server may not be running. Check that the
@@ -32,4 +31,3 @@ might be caused by one of the following things:
After you fix the problem, please restart the Pyramid application to
try it again.
"""
-