summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/tutorials/wiki2/definingmodels.rst32
-rw-r--r--docs/tutorials/wiki2/installation.rst7
-rw-r--r--docs/tutorials/wiki2/src/models/MANIFEST.in2
-rw-r--r--docs/tutorials/wiki2/src/models/production.ini2
-rw-r--r--docs/tutorials/wiki2/src/models/tutorial/__init__.py2
-rw-r--r--docs/tutorials/wiki2/src/models/tutorial/models/__init__.py71
-rw-r--r--docs/tutorials/wiki2/src/models/tutorial/models/meta.py33
-rw-r--r--docs/tutorials/wiki2/src/models/tutorial/models/mymodel.py3
-rw-r--r--docs/tutorials/wiki2/src/models/tutorial/scripts/initializedb.py27
-rw-r--r--docs/tutorials/wiki2/src/models/tutorial/templates/404.jinja28
-rw-r--r--docs/tutorials/wiki2/src/models/tutorial/tests.py18
-rw-r--r--docs/tutorials/wiki2/src/models/tutorial/views/default.py4
-rw-r--r--docs/tutorials/wiki2/src/models/tutorial/views/errors.py5
13 files changed, 133 insertions, 81 deletions
diff --git a/docs/tutorials/wiki2/definingmodels.rst b/docs/tutorials/wiki2/definingmodels.rst
index 9b517994f..b90bf77e6 100644
--- a/docs/tutorials/wiki2/definingmodels.rst
+++ b/docs/tutorials/wiki2/definingmodels.rst
@@ -3,7 +3,7 @@ Defining the Domain Model
=========================
The first change we'll make to our stock ``pcreate``-generated application will
-be to define a :term:`domain model` constructor representing a wiki page.
+be to define a wiki page :term:`domain model`.
We'll do this inside our ``mymodel.py`` file.
@@ -12,12 +12,12 @@ Edit ``mymodel.py``
.. note::
- There is nothing special about the filename ``mymodel.py``. A
- project may have many models throughout its codebase in arbitrarily named
- modules. Modules implementing models often have ``model`` in their
- names or they may live in a Python subpackage of your application package
- named ``models`` (as we've done in this tutorial), but this is only a
- convention and not a requirement.
+ There is nothing special about the filename ``mymodel.py`` except that it
+ is a Python module. A project may have many models throughout its codebase
+ in arbitrarily named modules. Modules implementing models often have
+ ``model`` in their names or they may live in a Python subpackage of your
+ application package named ``models`` (as we've done in this tutorial), but
+ this is only a convention and not a requirement.
Open the ``tutorial/models/mymodel.py`` file and edit it to look like
the following:
@@ -25,7 +25,7 @@ the following:
.. literalinclude:: src/models/tutorial/models/mymodel.py
:linenos:
:language: py
- :emphasize-lines: 9-11,13,14
+ :emphasize-lines: 10-12,14-15
The highlighted lines are the ones that need to be changed, as well as
removing lines that reference ``Index``.
@@ -34,7 +34,7 @@ The first thing we've done is remove the stock ``MyModel`` class
from the generated ``models.py`` file. The ``MyModel`` class is only a
sample and we're not going to use it.
-Then we added a ``Page`` class. Because this is an SQLAlchemy application,
+Then we added a ``Page`` class. Because this is a SQLAlchemy application,
this class inherits from an instance of
:func:`sqlalchemy.ext.declarative.declarative_base`.
@@ -43,7 +43,7 @@ this class inherits from an instance of
:linenos:
:language: python
-As you can see, our ``Page`` class has a class level attribute
+As you can see, our ``Page`` class has a class-level attribute
``__tablename__`` which equals the string ``'pages'``. This means that
SQLAlchemy will store our wiki data in a SQL table named ``pages``. Our
``Page`` class will also have class-level attributes named ``id``, ``name``,
@@ -58,7 +58,7 @@ Edit ``models/__init__.py``
---------------------------
Since we are using a package for our models, we also need to update our
-``__init__.py`` file.
+``__init__.py`` file to ensure that the model is attached to the metadata.
Open the ``tutorial/models/__init__.py`` file and edit it to look like
the following:
@@ -66,7 +66,7 @@ the following:
.. literalinclude:: src/models/tutorial/models/__init__.py
:linenos:
:language: py
- :emphasize-lines: 4
+ :emphasize-lines: 8
Here we need to align our import with the name of the model ``Page``.
@@ -83,7 +83,7 @@ Since we've changed our model, we need to make changes to our
``initializedb.py`` script. In particular, we'll replace our import of
``MyModel`` with one of ``Page`` and we'll change the very end of the script
to create a ``Page`` rather than a ``MyModel`` and add it to our
-``DBSession``.
+``dbsession``.
Open ``tutorial/scripts/initializedb.py`` and edit it to look like
the following:
@@ -91,11 +91,9 @@ the following:
.. literalinclude:: src/models/tutorial/scripts/initializedb.py
:linenos:
:language: python
- :emphasize-lines: 16,31,41
+ :emphasize-lines: 18,44-45
-Only the highlighted lines need to be changed, as well as removing the lines
-referencing ``pyramid.scripts.common`` and ``options`` under the ``main``
-function.
+Only the highlighted lines need to be changed.
Installing the project and re-initializing the database
diff --git a/docs/tutorials/wiki2/installation.rst b/docs/tutorials/wiki2/installation.rst
index 70d0444b7..5d6d8e56b 100644
--- a/docs/tutorials/wiki2/installation.rst
+++ b/docs/tutorials/wiki2/installation.rst
@@ -298,6 +298,13 @@ Initializing the database
We need to use the ``initialize_tutorial_db`` :term:`console
script` to initialize our database.
+.. note::
+
+ The ``initialize_tutorial_db`` command is not performing a migration but
+ rather simply creating missing tables and adding some dummy data. If you
+ already have a database, you should delete it before running
+ ``initialize_tutorial_db`` again.
+
Type the following command, making sure you are still in the ``tutorial``
directory (the directory with a ``development.ini`` in it):
diff --git a/docs/tutorials/wiki2/src/models/MANIFEST.in b/docs/tutorials/wiki2/src/models/MANIFEST.in
index 81beba1b1..42cd299b5 100644
--- a/docs/tutorials/wiki2/src/models/MANIFEST.in
+++ b/docs/tutorials/wiki2/src/models/MANIFEST.in
@@ -1,2 +1,2 @@
include *.txt *.ini *.cfg *.rst
-recursive-include tutorial *.ico *.png *.css *.gif *.jpg *.pt *.txt *.mak *.mako *.js *.html *.xml
+recursive-include tutorial *.ico *.png *.css *.gif *.jpg *.jinja2 *.pt *.txt *.mak *.mako *.js *.html *.xml
diff --git a/docs/tutorials/wiki2/src/models/production.ini b/docs/tutorials/wiki2/src/models/production.ini
index 97acfbd7d..cb1db3211 100644
--- a/docs/tutorials/wiki2/src/models/production.ini
+++ b/docs/tutorials/wiki2/src/models/production.ini
@@ -11,8 +11,6 @@ pyramid.debug_authorization = false
pyramid.debug_notfound = false
pyramid.debug_routematch = false
pyramid.default_locale_name = en
-pyramid.includes =
- pyramid_tm
sqlalchemy.url = sqlite:///%(here)s/tutorial.sqlite
diff --git a/docs/tutorials/wiki2/src/models/tutorial/__init__.py b/docs/tutorials/wiki2/src/models/tutorial/__init__.py
index 7994bbfa8..17763812a 100644
--- a/docs/tutorials/wiki2/src/models/tutorial/__init__.py
+++ b/docs/tutorials/wiki2/src/models/tutorial/__init__.py
@@ -6,7 +6,7 @@ def main(global_config, **settings):
"""
config = Configurator(settings=settings)
config.include('pyramid_jinja2')
- config.include('.models.meta')
+ config.include('.models')
config.add_static_view('static', 'static', cache_max_age=3600)
config.add_route('home', '/')
config.scan()
diff --git a/docs/tutorials/wiki2/src/models/tutorial/models/__init__.py b/docs/tutorials/wiki2/src/models/tutorial/models/__init__.py
index 7b1c62867..4810c357a 100644
--- a/docs/tutorials/wiki2/src/models/tutorial/models/__init__.py
+++ b/docs/tutorials/wiki2/src/models/tutorial/models/__init__.py
@@ -1,7 +1,72 @@
+from sqlalchemy import engine_from_config
+from sqlalchemy.orm import sessionmaker
from sqlalchemy.orm import configure_mappers
-# import all models classes here for sqlalchemy mappers
-# to pick up
+import zope.sqlalchemy
+
+# import or define all models here to ensure they are attached to the
+# Base.metadata prior to any initialization routines
from .mymodel import Page # flake8: noqa
-# run configure mappers to ensure we avoid any race conditions
+# run configure_mappers after defining all of the models to ensure
+# all relationships can be setup
configure_mappers()
+
+
+def get_engine(settings, prefix='sqlalchemy.'):
+ return engine_from_config(settings, prefix)
+
+
+def get_session_factory(engine):
+ factory = sessionmaker()
+ factory.configure(bind=engine)
+ return factory
+
+
+def get_tm_session(session_factory, transaction_manager):
+ """
+ Get a ``sqlalchemy.orm.Session`` instance backed by a transaction.
+
+ This function will hook the session to the transaction manager which
+ will take care of committing any changes.
+
+ - When using pyramid_tm it will automatically be committed or aborted
+ depending on whether an exception is raised.
+
+ - When using scripts you should wrap the session in a manager yourself.
+ For example::
+
+ import transaction
+
+ engine = get_engine(settings)
+ session_factory = get_session_factory(engine)
+ with transaction.manager:
+ dbsession = get_tm_session(session_factory, transaction.manager)
+
+ """
+ dbsession = session_factory()
+ zope.sqlalchemy.register(
+ dbsession, transaction_manager=transaction_manager)
+ return dbsession
+
+
+def includeme(config):
+ """
+ Initialize the model for a Pyramid app.
+
+ Activate this setup using ``config.include('tutorial.models')``.
+
+ """
+ settings = config.get_settings()
+
+ # use pyramid_tm to hook the transaction lifecycle to the request
+ config.include('pyramid_tm')
+
+ session_factory = get_session_factory(get_engine(settings))
+
+ # make request.dbsession available for use in Pyramid
+ config.add_request_method(
+ # r.tm is the transaction manager used by pyramid_tm
+ lambda r: get_tm_session(session_factory, r.tm),
+ 'dbsession',
+ reify=True
+ )
diff --git a/docs/tutorials/wiki2/src/models/tutorial/models/meta.py b/docs/tutorials/wiki2/src/models/tutorial/models/meta.py
index 80ececd8c..fc3e8f1dd 100644
--- a/docs/tutorials/wiki2/src/models/tutorial/models/meta.py
+++ b/docs/tutorials/wiki2/src/models/tutorial/models/meta.py
@@ -1,8 +1,5 @@
-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
# Recommended naming convention used by Alembic, as various different database
# providers will autogenerate vastly different names making migrations more
@@ -17,33 +14,3 @@ NAMING_CONVENTION = {
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/models/tutorial/models/mymodel.py b/docs/tutorials/wiki2/src/models/tutorial/models/mymodel.py
index 45571d78e..b23d0c0d2 100644
--- a/docs/tutorials/wiki2/src/models/tutorial/models/mymodel.py
+++ b/docs/tutorials/wiki2/src/models/tutorial/models/mymodel.py
@@ -1,10 +1,11 @@
-from .meta import Base
from sqlalchemy import (
Column,
Integer,
Text,
)
+from .meta import Base
+
class Page(Base):
""" The SQLAlchemy declarative model class for a Page object. """
diff --git a/docs/tutorials/wiki2/src/models/tutorial/scripts/initializedb.py b/docs/tutorials/wiki2/src/models/tutorial/scripts/initializedb.py
index 4aac4a848..601a6e73f 100644
--- a/docs/tutorials/wiki2/src/models/tutorial/scripts/initializedb.py
+++ b/docs/tutorials/wiki2/src/models/tutorial/scripts/initializedb.py
@@ -7,13 +7,15 @@ from pyramid.paster import (
setup_logging,
)
-from ..models.meta import (
- Base,
- get_session,
+from pyramid.scripts.common import parse_vars
+
+from ..models.meta import Base
+from ..models import (
get_engine,
- get_dbmaker,
+ get_session_factory,
+ get_tm_session,
)
-from ..models.mymodel import Page
+from ..models import Page
def usage(argv):
@@ -27,16 +29,17 @@ def main(argv=sys.argv):
if len(argv) < 2:
usage(argv)
config_uri = argv[1]
+ options = parse_vars(argv[2:])
setup_logging(config_uri)
- settings = get_appsettings(config_uri)
+ 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)
+ session_factory = get_session_factory(engine)
+
with transaction.manager:
- model = Page(name='FrontPage', data='This is the front page')
- dbsession.add(model)
+ dbsession = get_tm_session(session_factory, transaction.manager)
+
+ page = Page(name='FrontPage', data='This is the front page')
+ dbsession.add(page)
diff --git a/docs/tutorials/wiki2/src/models/tutorial/templates/404.jinja2 b/docs/tutorials/wiki2/src/models/tutorial/templates/404.jinja2
new file mode 100644
index 000000000..1917f83c7
--- /dev/null
+++ b/docs/tutorials/wiki2/src/models/tutorial/templates/404.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"><span class="font-semi-bold">404</span> Page Not Found</p>
+</div>
+{% endblock content %}
diff --git a/docs/tutorials/wiki2/src/models/tutorial/tests.py b/docs/tutorials/wiki2/src/models/tutorial/tests.py
index b947e3bb1..c54945c28 100644
--- a/docs/tutorials/wiki2/src/models/tutorial/tests.py
+++ b/docs/tutorials/wiki2/src/models/tutorial/tests.py
@@ -13,22 +13,22 @@ class BaseTest(unittest.TestCase):
self.config = testing.setUp(settings={
'sqlalchemy.url': 'sqlite:///:memory:'
})
- self.config.include('.models.meta')
+ self.config.include('.models')
settings = self.config.get_settings()
- from .models.meta import (
- get_session,
+ from .models import (
get_engine,
- get_dbmaker,
+ get_session_factory,
+ get_tm_session,
)
self.engine = get_engine(settings)
- dbmaker = get_dbmaker(self.engine)
+ session_factory = get_session_factory(self.engine)
- self.session = get_session(transaction.manager, dbmaker)
+ self.session = get_tm_session(session_factory, transaction.manager)
def init_database(self):
- from .models.meta import Base
+ from .models import Base
Base.metadata.create_all(self.engine)
def tearDown(self):
@@ -36,7 +36,7 @@ class BaseTest(unittest.TestCase):
testing.tearDown()
transaction.abort()
- Base.metadata.create_all(self.engine)
+ Base.metadata.drop_all(self.engine)
class TestMyViewSuccessCondition(BaseTest):
@@ -45,7 +45,7 @@ class TestMyViewSuccessCondition(BaseTest):
super(TestMyViewSuccessCondition, self).setUp()
self.init_database()
- from .models.mymodel import MyModel
+ from .models import MyModel
model = MyModel(name='one', value=55)
self.session.add(model)
diff --git a/docs/tutorials/wiki2/src/models/tutorial/views/default.py b/docs/tutorials/wiki2/src/models/tutorial/views/default.py
index 13ad8793c..ad0c728d7 100644
--- a/docs/tutorials/wiki2/src/models/tutorial/views/default.py
+++ b/docs/tutorials/wiki2/src/models/tutorial/views/default.py
@@ -3,7 +3,7 @@ from pyramid.view import view_config
from sqlalchemy.exc import DBAPIError
-from ..models.mymodel import MyModel
+from ..models import MyModel
@view_config(route_name='home', renderer='../templates/mytemplate.jinja2')
@@ -12,7 +12,7 @@ def my_view(request):
query = request.dbsession.query(MyModel)
one = query.filter(MyModel.name == 'one').first()
except DBAPIError:
- return Response(db_err_msg, content_type='text/plain', status_int=500)
+ return Response(db_err_msg, content_type='text/plain', status=500)
return {'one': one, 'project': 'tutorial'}
diff --git a/docs/tutorials/wiki2/src/models/tutorial/views/errors.py b/docs/tutorials/wiki2/src/models/tutorial/views/errors.py
new file mode 100644
index 000000000..a4b8201f1
--- /dev/null
+++ b/docs/tutorials/wiki2/src/models/tutorial/views/errors.py
@@ -0,0 +1,5 @@
+from pyramid.view import notfound_view_config
+
+@notfound_view_config(renderer='../templates/404.jinja2')
+def notfound_view(request):
+ return {}