quick_tour - "Databases" updates for cookiecutter
- add src files
- adjust line numbers
1 files deleted
16 files modified
| | |
| | | #. ``project_name [Pyramid Scaffold]: hello_world`` |
| | | #. ``repo_name [scaffold]: hello_world`` |
| | | |
| | | We then run through the following commands |
| | | We then run through the following commands. |
| | | |
| | | .. code-block:: bash |
| | | |
| | |
| | | # ...and into which we install our project and its testing requirements. |
| | | $ env/bin/pip install -e ".[testing]" |
| | | # Reset our environment variable for a new virtual environment. |
| | | $ export VENV=~/env/hello_world/env |
| | | $ export VENV=~/hello_world/env |
| | | |
| | | We are moving in the direction of a full-featured Pyramid project, with a |
| | | proper setup for Python standards (packaging) and Pyramid configuration. This |
| | |
| | | usually leads to the mega-quality *SQLAlchemy*, a Python package that greatly |
| | | eases working with databases. |
| | | |
| | | Pyramid and SQLAlchemy are great friends. That friendship includes a scaffold! |
| | | Pyramid and SQLAlchemy are great friends. That friendship includes a cookiecutter! |
| | | |
| | | .. code-block:: bash |
| | | |
| | | $ $VENV/bin/pcreate --scaffold alchemy sqla_demo |
| | | $ cd sqla_demo |
| | | $ $VENV/bin/pip install -e . |
| | | $ cd ~ |
| | | $ env/bin/cookiecutter https://github.com/Pylons/pyramid-cookiecutter-alchemy |
| | | |
| | | If prompted for the first item, accept the default ``yes`` by hitting return. |
| | | |
| | | #. ``You've cloned ~/.cookiecutters/pyramid-cookiecutter-alchemy before. Is it |
| | | okay to delete and re-clone it? [yes]:`` |
| | | #. ``project_name [Pyramid Scaffold]: sqla_demo`` |
| | | #. ``repo_name [scaffold]: sqla_demo`` |
| | | |
| | | We then run through the following commands as before. |
| | | |
| | | .. code-block:: bash |
| | | |
| | | # Change directory into your newly created project. |
| | | $ cd sqla_demo |
| | | # Create a new virtual environment... |
| | | $ python3 -m venv env |
| | | # ...where we upgrade packaging tools... |
| | | $ env/bin/pip install --upgrade pip setuptools |
| | | # ...and into which we install our project and its testing requirements. |
| | | $ env/bin/pip install -e ".[testing]" |
| | | # Reset our environment variable for a new virtual environment. |
| | | $ export VENV=~/sqla_demo/env |
| | | |
| | | We now have a working sample SQLAlchemy application with all dependencies |
| | | installed. The sample project provides a console script to initialize a SQLite |
| | |
| | | |
| | | .. literalinclude:: quick_tour/sqla_demo/sqla_demo/models/mymodel.py |
| | | :language: python |
| | | :start-after: Start Sphinx Include |
| | | :end-before: End Sphinx Include |
| | | :lineno-match: |
| | | :pyobject: MyModel |
| | | |
| | | View code, which mediates the logic between web requests and the rest of the |
| | | system, can then easily get at the data thanks to SQLAlchemy: |
| | | |
| | | .. literalinclude:: quick_tour/sqla_demo/sqla_demo/views/default.py |
| | | :language: python |
| | | :start-after: Start Sphinx Include |
| | | :end-before: End Sphinx Include |
| | | :lineno-match: |
| | | :lines: 13 |
| | | |
| | | .. seealso:: See also: |
| | | :ref:`Quick Tutorial Databases <qtut_databases>`, `SQLAlchemy |
| | |
| | | 0.0 |
| | | --- |
| | | |
| | | - Initial version |
| | | - Initial version. |
| | |
| | | include *.txt *.ini *.cfg *.rst |
| | | recursive-include sqla_demo *.ico *.png *.css *.gif *.jpg *.pt *.txt *.mak *.mako *.js *.html *.xml |
| | | recursive-include sqla_demo *.ico *.png *.css *.gif *.jpg *.pt *.txt *.mak *.mako *.js *.html *.xml *.jinja2 |
| | |
| | | sqla_demo README |
| | | ================== |
| | | sqla_demo |
| | | =============================== |
| | | |
| | | Getting Started |
| | | --------------- |
| | | |
| | | - cd <directory containing this file> |
| | | - Change directory into your newly created project. |
| | | |
| | | - $VENV/bin/pip install -e . |
| | | cd sqla_demo |
| | | |
| | | - $VENV/bin/initialize_sqla_demo_db development.ini |
| | | - Create a Python virtual environment. |
| | | |
| | | - $VENV/bin/pserve development.ini |
| | | python3 -m venv env |
| | | |
| | | - Upgrade packaging tools. |
| | | |
| | | env/bin/pip install --upgrade pip setuptools |
| | | |
| | | - Install the project in editable mode with its testing requirements. |
| | | |
| | | env/bin/pip install -e ".[testing]" |
| | | |
| | | - Configure the database. |
| | | |
| | | env/bin/initialize_sqla_demo_db development.ini |
| | | |
| | | - Run your project's tests. |
| | | |
| | | env/bin/pytest |
| | | |
| | | - Run your project. |
| | | |
| | | env/bin/pserve development.ini |
| | |
| | | pyramid.default_locale_name = en |
| | | pyramid.includes = |
| | | pyramid_debugtoolbar |
| | | pyramid_tm |
| | | |
| | | sqlalchemy.url = sqlite:///%(here)s/sqla_demo.sqlite |
| | | |
| | |
| | | pyramid.debug_notfound = false |
| | | pyramid.debug_routematch = false |
| | | pyramid.default_locale_name = en |
| | | pyramid.includes = |
| | | pyramid_tm |
| | | |
| | | sqlalchemy.url = sqlite:///%(here)s/sqla_demo.sqlite |
| | | |
| | | ### |
| | | # wsgi server configuration |
| | | ### |
| | | |
| | | [server:main] |
| | | use = egg:waitress#main |
| | | listen = *:6543 |
| | |
| | | 'transaction', |
| | | 'zope.sqlalchemy', |
| | | 'waitress', |
| | | ] |
| | | ] |
| | | |
| | | setup(name='sqla_demo', |
| | | version='0.0', |
| | | description='sqla_demo', |
| | | long_description=README + '\n\n' + CHANGES, |
| | | classifiers=[ |
| | | "Programming Language :: Python", |
| | | "Framework :: Pyramid", |
| | | "Topic :: Internet :: WWW/HTTP", |
| | | "Topic :: Internet :: WWW/HTTP :: WSGI :: Application", |
| | | tests_require = [ |
| | | 'WebTest >= 1.3.1', # py3 compat |
| | | 'pytest', |
| | | 'pytest-cov', |
| | | ] |
| | | |
| | | setup( |
| | | name='sqla_demo', |
| | | version='0.0', |
| | | description='sqla_demo', |
| | | long_description=README + '\n\n' + CHANGES, |
| | | classifiers=[ |
| | | 'Programming Language :: Python', |
| | | 'Framework :: Pyramid', |
| | | 'Topic :: Internet :: WWW/HTTP', |
| | | 'Topic :: Internet :: WWW/HTTP :: WSGI :: Application', |
| | | ], |
| | | author='', |
| | | author_email='', |
| | | url='', |
| | | keywords='web pyramid pylons', |
| | | packages=find_packages(), |
| | | include_package_data=True, |
| | | zip_safe=False, |
| | | extras_require={ |
| | | 'testing': tests_require, |
| | | }, |
| | | install_requires=requires, |
| | | entry_points={ |
| | | 'paste.app_factory': [ |
| | | 'main = sqla_demo:main', |
| | | ], |
| | | author='', |
| | | author_email='', |
| | | url='', |
| | | keywords='web wsgi bfg pylons pyramid', |
| | | packages=find_packages(), |
| | | include_package_data=True, |
| | | zip_safe=False, |
| | | test_suite='sqla_demo', |
| | | install_requires=requires, |
| | | entry_points="""\ |
| | | [paste.app_factory] |
| | | main = sqla_demo:main |
| | | [console_scripts] |
| | | initialize_sqla_demo_db = sqla_demo.scripts.initializedb:main |
| | | """, |
| | | ) |
| | | 'console_scripts': [ |
| | | 'initialize_sqla_demo_db = sqla_demo.scripts.initializedb:main', |
| | | ], |
| | | }, |
| | | ) |
| | |
| | | """ |
| | | config = Configurator(settings=settings) |
| | | config.include('pyramid_jinja2') |
| | | config.include('.models.meta') |
| | | config.add_static_view('static', 'static', cache_max_age=3600) |
| | | config.add_route('home', '/') |
| | | config.include('.models') |
| | | config.include('.routes') |
| | | config.scan() |
| | | return config.make_wsgi_app() |
| | |
| | | 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 |
| | | from .mymodel import MyModel # noqa |
| | | import zope.sqlalchemy |
| | | |
| | | # run configure mappers to ensure we avoid any race conditions |
| | | # import or define all models here to ensure they are attached to the |
| | | # Base.metadata prior to any initialization routines |
| | | from .mymodel import MyModel # flake8: noqa |
| | | |
| | | # 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('sqla_demo.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)) |
| | | config.registry['dbsession_factory'] = session_factory |
| | | |
| | | # 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 |
| | | ) |
| | |
| | | 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 |
| | |
| | | |
| | | 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 |
| | |
| | | from .meta import Base |
| | | from sqlalchemy import ( |
| | | Column, |
| | | Index, |
| | |
| | | Text, |
| | | ) |
| | | |
| | | from .meta import Base |
| | | |
| | | # Start Sphinx Include |
| | | |
| | | class MyModel(Base): |
| | | __tablename__ = 'models' |
| | | id = Column(Integer, primary_key=True) |
| | | name = Column(Text) |
| | | value = Column(Integer) |
| | | # End Sphinx Include |
| | | |
| | | |
| | | Index('my_index', MyModel.name, unique=True, mysql_length=255) |
| | |
| | | |
| | | from pyramid.scripts.common import parse_vars |
| | | |
| | | from ..models.meta import ( |
| | | Base, |
| | | get_session, |
| | | from ..models.meta import Base |
| | | from ..models import ( |
| | | get_engine, |
| | | get_dbmaker, |
| | | get_session_factory, |
| | | get_tm_session, |
| | | ) |
| | | from ..models.mymodel import MyModel |
| | | from ..models import MyModel |
| | | |
| | | |
| | | def usage(argv): |
| | |
| | | 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: |
| | | dbsession = get_tm_session(session_factory, transaction.manager) |
| | | |
| | | model = MyModel(name='one', value=1) |
| | | dbsession.add(model) |
| | |
| | | <meta name="author" content="Pylons Project"> |
| | | <link rel="shortcut icon" href="{{request.static_url('sqla_demo:static/pyramid-16x16.png')}}"> |
| | | |
| | | <title>Alchemy Scaffold for The Pyramid Web Framework</title> |
| | | <title>Cookiecutter Alchemy project 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"> |
| | |
| | | <div class="container"> |
| | | <div class="row"> |
| | | <div class="col-md-2"> |
| | | <img class="logo img-responsive" src="{{request.static_url('sqla_demo:static/pyramid.png')}}" alt="pyramid web framework"> |
| | | <img class="logo img-responsive" src="{{request.static_url('sqla_demo:static/pyramid.png') }}" alt="pyramid web framework"> |
| | | </div> |
| | | <div class="col-md-10"> |
| | | {% block content %} |
| | |
| | | <div class="row"> |
| | | <div class="links"> |
| | | <ul> |
| | | <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-globe icon-muted"></i><a href="https://webchat.freenode.net/?channels=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> |
| | |
| | | |
| | | {% 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 application generated by<br>the <span class="font-normal">Pyramid Web Framework 1.7.dev0</span>.</p> |
| | | <h1><span class="font-semi-bold">Pyramid</span> <span class="smaller">Alchemy project</span></h1> |
| | | <p class="lead">Welcome to <span class="font-normal">sqla_demo</span>, a Pyramid application generated by<br><span class="font-normal">Cookiecutter</span>.</p> |
| | | </div> |
| | | {% endblock content %} |
| | |
| | | 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 |
| | |
| | | |
| | | testing.tearDown() |
| | | transaction.abort() |
| | | Base.metadata.create_all(self.engine) |
| | | Base.metadata.drop_all(self.engine) |
| | | |
| | | |
| | | 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) |
| | |
| | | |
| | | from sqlalchemy.exc import DBAPIError |
| | | |
| | | from ..models.mymodel import MyModel |
| | | from ..models import MyModel |
| | | |
| | | |
| | | @view_config(route_name='home', renderer='../templates/mytemplate.jinja2') |
| | | def my_view(request): |
| | | try: |
| | | query = request.dbsession.query(MyModel) |
| | | # Start Sphinx Include |
| | | one = query.filter(MyModel.name == 'one').first() |
| | | # End Sphinx Include |
| | | 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': 'sqla_demo'} |
| | | |
| | | |