Restore progress after backing changes out of master.
This reverts commit 049e670aef9ea5611561546fd5c0e2dd6152b9b7.
12 files deleted
1 files copied
13 files added
17 files modified
3 files renamed
| | |
| | | |
| | | - Donald Stufft, 2015/03/15 |
| | | |
| | | - Randy Topliffe, 2015/04/14 |
| | | |
| | | - Karen Dalton, 2015/06/01 |
| | | |
| | | - Igor Stroh, 2015/06/10 |
| | |
| | | language. SQLAlchemy uses "models" for this mapping. The scaffold |
| | | generated a sample model: |
| | | |
| | | .. literalinclude:: quick_tour/sqla_demo/sqla_demo/models.py |
| | | .. literalinclude:: quick_tour/sqla_demo/sqla_demo/models/mymodel.py |
| | | :start-after: Start Sphinx Include |
| | | :end-before: End Sphinx Include |
| | | |
| | | 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.py |
| | | .. literalinclude:: quick_tour/sqla_demo/sqla_demo/views/default.py |
| | | :start-after: Start Sphinx Include |
| | | :end-before: End Sphinx Include |
| | | |
| | |
| | | |
| | | [server:main] |
| | | use = egg:waitress#main |
| | | host = 0.0.0.0 |
| | | host = 127.0.0.1 |
| | | port = 6543 |
| | | |
| | | ### |
| | |
| | | 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 |
| | |
| | | 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 |
| | |
| | | from setuptools import setup, find_packages |
| | | |
| | | here = os.path.abspath(os.path.dirname(__file__)) |
| | | README = open(os.path.join(here, 'README.txt')).read() |
| | | CHANGES = open(os.path.join(here, 'CHANGES.txt')).read() |
| | | with open(os.path.join(here, 'README.txt')) as f: |
| | | README = f.read() |
| | | with open(os.path.join(here, 'CHANGES.txt')) as f: |
| | | CHANGES = f.read() |
| | | |
| | | requires = [ |
| | | 'pyramid', |
| | | 'pyramid_jinja2', |
| | | 'pyramid_debugtoolbar', |
| | | 'pyramid_tm', |
| | | 'SQLAlchemy', |
| | | 'transaction', |
| | | 'pyramid_tm', |
| | | 'pyramid_debugtoolbar', |
| | | 'zope.sqlalchemy', |
| | | 'waitress', |
| | | ] |
| | |
| | | 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_jinja2') |
| | | config.include('.models.meta') |
| | | config.add_static_view('static', 'static', cache_max_age=3600) |
| | | config.add_route('home', '/') |
| | | config.scan() |
New file |
| | |
| | | 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() |
New file |
| | |
| | | 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 |
New file |
| | |
| | | from .meta import Base |
| | | from sqlalchemy import ( |
| | | Column, |
| | | Index, |
| | | Integer, |
| | | Text, |
| | | ) |
| | | |
| | | |
| | | # 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) |
| | |
| | | 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) |
New 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: #ffffff; |
| | | 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: #ffffff; |
| | | } |
| | | .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: #ffffff; |
| | | text-decoration: underline; |
| | | } |
| | | .starter-template .links ul li .icon-muted { |
| | | color: #eb8b95; |
| | | margin-right: 5px; |
| | | } |
| | | .starter-template .links ul li:hover .icon-muted { |
| | | color: #ffffff; |
| | | } |
| | | .starter-template .copyright { |
| | | margin-top: 10px; |
| | | font-size: 0.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; |
| | | } |
| | | } |
New 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}} |
copy from pyramid/scaffolds/alchemy/+package+/templates/mytemplate.pt_tmpl
copy to docs/quick_tour/sqla_demo/sqla_demo/templates/layout.jinja2
File was copied from pyramid/scaffolds/alchemy/+package+/templates/mytemplate.pt_tmpl |
| | |
| | | <!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('{{package}}:static/pyramid-16x16.png')}"> |
| | | <link rel="shortcut icon" href="{{request.static_url('sqla_demo:static/pyramid-16x16.png')}}"> |
| | | |
| | | <title>Alchemy Scaffold for The Pyramid Web Framework</title> |
| | | |
| | |
| | | <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('{{package}}:static/theme.css')}" rel="stylesheet"> |
| | | <link href="{{request.static_url('sqla_demo:static/theme.css')}}" rel="stylesheet"> |
| | | |
| | | <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries --> |
| | | <!--[if lt IE 9]> |
| | |
| | | <div class="container"> |
| | | <div class="row"> |
| | | <div class="col-md-2"> |
| | | <img class="logo img-responsive" src="${request.static_url('{{package}}: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"> |
| | | <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 {{pyramid_version}}</span>.</p> |
| | | </div> |
| | | {% block content %} |
| | | <p>No content</p> |
| | | {% endblock content %} |
| | | </div> |
| | | </div> |
| | | <div class="row"> |
| | | <div class="links"> |
| | | <ul> |
| | | <li class="current-version">Generated by v{{pyramid_version}}</li> |
| | | <li><i class="glyphicon glyphicon-bookmark icon-muted"></i><a href="http://docs.pylonsproject.org/projects/pyramid/en/{{pyramid_docs_branch}}/">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> |
New file |
| | |
| | | {% 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 application generated by<br>the <span class="font-normal">Pyramid Web Framework 1.7.dev0</span>.</p> |
| | | </div> |
| | | {% endblock content %} |
| | |
| | | |
| | | 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() |
| | | testing.tearDown() |
| | | from .models.meta import Base |
| | | |
| | | def test_it(self): |
| | | from .views import my_view |
| | | request = testing.DummyRequest() |
| | | info = my_view(request) |
| | | testing.tearDown() |
| | | transaction.abort() |
| | | Base.metadata.create_all(self.engine) |
| | | |
| | | |
| | | class TestMyViewSuccessCondition(BaseTest): |
| | | |
| | | 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'], 'sqla_demo') |
| | | |
| | | |
| | | 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) |
File was renamed from docs/quick_tour/sqla_demo/sqla_demo/views.py |
| | |
| | | |
| | | 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: |
| | | query = request.dbsession.query(MyModel) |
| | | # Start Sphinx Include |
| | | one = DBSession.query(MyModel).filter(MyModel.name == 'one').first() |
| | | one = query.filter(MyModel.name == 'one').first() |
| | | # End Sphinx Include |
| | | 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': 'sqla_demo'} |
| | | |
| | | 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_sqla_demo_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 |
| | |
| | | After you fix the problem, please restart the Pyramid application to |
| | | try it again. |
| | | """ |
| | | |
| | |
| | | |
| | | A directory on disk can be turned into a Python :term:`package` by containing |
| | | an ``__init__.py`` file. Even if empty, this marks a directory as a Python |
| | | package. We use ``__init__.py`` both as a marker, indicating the directory |
| | | in which it's contained is a package, and to contain application configuration |
| | | package. We use ``__init__.py`` both as a marker, indicating the directory in |
| | | which it's contained is a package, and to contain application configuration |
| | | code. |
| | | |
| | | Open ``tutorial/tutorial/__init__.py``. It should already contain |
| | | the following: |
| | | Open ``tutorial/tutorial/__init__.py``. It should already contain the |
| | | following: |
| | | |
| | | .. literalinclude:: src/basiclayout/tutorial/__init__.py |
| | | :linenos: |
| | |
| | | above is executed. It accepts some settings and returns a :term:`WSGI` |
| | | application. (See :ref:`startup_chapter` for more about ``pserve``.) |
| | | |
| | | 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://``): |
| | | |
| | | .. literalinclude:: src/basiclayout/tutorial/__init__.py |
| | | :lines: 13 |
| | | :language: py |
| | | |
| | | ``main`` then initializes our SQLAlchemy session object, passing it the |
| | | engine: |
| | | |
| | | .. literalinclude:: src/basiclayout/tutorial/__init__.py |
| | | :lines: 14 |
| | | :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. |
| | | |
| | | .. literalinclude:: src/basiclayout/tutorial/__init__.py |
| | | :lines: 15 |
| | | :language: py |
| | | |
| | | The next step of ``main`` is to construct a :term:`Configurator` object: |
| | | |
| | | .. literalinclude:: src/basiclayout/tutorial/__init__.py |
| | | :lines: 16 |
| | | :lines: 7 |
| | | :language: py |
| | | |
| | | ``settings`` is passed to the Configurator as a keyword argument with the |
| | | dictionary values passed as the ``**settings`` argument. This will be a |
| | | dictionary of settings parsed from the ``.ini`` file, which contains |
| | | deployment-related values such as ``pyramid.reload_templates``, |
| | | ``db_string``, etc. |
| | | ``sqlalchemy.url``, and so on. |
| | | |
| | | Next, include :term:`Chameleon` templating bindings so that we can use |
| | | renderers with the ``.pt`` extension within our project. |
| | | Next include :term:`Jinja2` templating bindings so that we can use renderers |
| | | with the ``.jinja2`` extension within our project. |
| | | |
| | | .. literalinclude:: src/basiclayout/tutorial/__init__.py |
| | | :lines: 17 |
| | | :lines: 8 |
| | | :language: py |
| | | |
| | | Next include the module ``meta`` from the package ``models`` using a dotted |
| | | Python path. |
| | | |
| | | .. literalinclude:: src/basiclayout/tutorial/__init__.py |
| | | :lines: 9 |
| | | :language: py |
| | | |
| | | ``main`` now calls :meth:`pyramid.config.Configurator.add_static_view` with |
| | | two arguments: ``static`` (the name), and ``static`` (the path): |
| | | |
| | | .. literalinclude:: src/basiclayout/tutorial/__init__.py |
| | | :lines: 18 |
| | | :lines: 10 |
| | | :language: py |
| | | |
| | | This registers a static resource view which will match any URL that starts |
| | |
| | | used when the URL is ``/``: |
| | | |
| | | .. literalinclude:: src/basiclayout/tutorial/__init__.py |
| | | :lines: 19 |
| | | :lines: 11 |
| | | :language: py |
| | | |
| | | Since this route has a ``pattern`` equaling ``/`` it is the route that will |
| | | be matched when the URL ``/`` is visited, e.g. ``http://localhost:6543/``. |
| | | Since this route has a ``pattern`` equaling ``/``, it is the route that will |
| | | be matched when the URL ``/`` is visited, e.g., ``http://localhost:6543/``. |
| | | |
| | | ``main`` next calls the ``scan`` method of the configurator |
| | | (:meth:`pyramid.config.Configurator.scan`), which will recursively scan our |
| | |
| | | application URLs to be mapped to some code. |
| | | |
| | | .. literalinclude:: src/basiclayout/tutorial/__init__.py |
| | | :lines: 20 |
| | | :lines: 12 |
| | | :language: py |
| | | |
| | | Finally, ``main`` is finished configuring things, so it uses the |
| | | Finally ``main`` is finished configuring things, so it uses the |
| | | :meth:`pyramid.config.Configurator.make_wsgi_app` method to return a |
| | | :term:`WSGI` application: |
| | | |
| | |
| | | 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. |
| | | |
| | | 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://``): |
| | | |
| | | .. literalinclude:: src/basiclayout/tutorial/__init__.py |
| | | :lines: 13 |
| | | :language: py |
| | | |
| | | ``main`` then initializes our SQLAlchemy session object, passing it the |
| | | engine: |
| | | |
| | | .. literalinclude:: src/basiclayout/tutorial/__init__.py |
| | | :lines: 14 |
| | | :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. |
| | | |
| | | .. literalinclude:: src/basiclayout/tutorial/__init__.py |
| | | :lines: 15 |
| | | :language: py |
| | | |
| | | .. END moved from Application configuration with ``__init__.py`` |
| | | |
| | | 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. |
| | |
| | | |
| | | [server:main] |
| | | use = egg:waitress#main |
| | | host = 0.0.0.0 |
| | | host = 127.0.0.1 |
| | | port = 6543 |
| | | |
| | | ### |
| | |
| | | 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 |
| | |
| | | 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 |
| | |
| | | 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('home', '/') |
| | | config.scan() |
| | |
| | | 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('home', '/') |
| | | config.scan() |
New file |
| | |
| | | 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() |
New file |
| | |
| | | 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 |
New file |
| | |
| | | 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) |
| | |
| | | import sys |
| | | import transaction |
| | | |
| | | from sqlalchemy import engine_from_config |
| | | |
| | | from pyramid.paster import ( |
| | | get_appsettings, |
| | | setup_logging, |
| | |
| | | |
| | | from pyramid.scripts.common import parse_vars |
| | | |
| | | from ..models import ( |
| | | DBSession, |
| | | MyModel, |
| | | from ..models.meta import ( |
| | | Base, |
| | | get_session, |
| | | get_engine, |
| | | get_dbmaker, |
| | | ) |
| | | from ..models.mymodel import MyModel |
| | | |
| | | |
| | | def usage(argv): |
| | |
| | | options = parse_vars(argv[2:]) |
| | | setup_logging(config_uri) |
| | | settings = get_appsettings(config_uri, options=options) |
| | | 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 = MyModel(name='one', value=1) |
| | | DBSession.add(model) |
| | | dbsession.add(model) |
File was renamed from pyramid/scaffolds/alchemy/+package+/templates/mytemplate.pt_tmpl |
| | |
| | | <!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('{{package}}:static/pyramid-16x16.png')}"> |
| | | <link rel="shortcut icon" href="\{\{request.static_url('{{package}}:static/pyramid-16x16.png')\}\}"> |
| | | |
| | | <title>Alchemy Scaffold for The Pyramid Web Framework</title> |
| | | |
| | |
| | | <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('{{package}}:static/theme.css')}" rel="stylesheet"> |
| | | <link href="\{\{request.static_url('{{package}}:static/theme.css')\}\}" rel="stylesheet"> |
| | | |
| | | <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries --> |
| | | <!--[if lt IE 9]> |
| | |
| | | <div class="container"> |
| | | <div class="row"> |
| | | <div class="col-md-2"> |
| | | <img class="logo img-responsive" src="${request.static_url('{{package}}:static/pyramid.png')}" alt="pyramid web framework"> |
| | | <img class="logo img-responsive" src="\{\{request.static_url('{{package}}: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 application generated by<br>the <span class="font-normal">Pyramid Web Framework {{pyramid_version}}</span>.</p> |
| | | </div> |
| | | {% block content %} |
| | | <p>No content</p> |
| | | {% endblock content %} |
| | | </div> |
| | | </div> |
| | | <div class="row"> |
New file |
| | |
| | | {% 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 application generated by<br>the <span class="font-normal">Pyramid Web Framework {{pyramid_version}}</span>.</p> |
| | | </div> |
| | | {% endblock content %} |
| | |
| | | |
| | | from pyramid import testing |
| | | |
| | | from .models import DBSession |
| | | |
| | | def dummy_request(dbsession): |
| | | return testing.DummyRequest(dbsession=dbsession) |
| | | |
| | | |
| | | class TestMyViewSuccessCondition(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 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 import my_view |
| | | request = testing.DummyRequest() |
| | | info = my_view(request) |
| | | from .views.default import my_view |
| | | info = my_view(dummy_request(self.session)) |
| | | self.assertEqual(info['one'].name, 'one') |
| | | self.assertEqual(info['project'], '{{project}}') |
| | | |
| | | |
| | | class TestMyViewFailureCondition(unittest.TestCase): |
| | | def setUp(self): |
| | | self.config = testing.setUp() |
| | | from sqlalchemy import create_engine |
| | | engine = create_engine('sqlite://') |
| | | from .models import ( |
| | | Base, |
| | | MyModel, |
| | | ) |
| | | DBSession.configure(bind=engine) |
| | | |
| | | def tearDown(self): |
| | | DBSession.remove() |
| | | testing.tearDown() |
| | | class TestMyViewFailureCondition(BaseTest): |
| | | |
| | | def test_failing_view(self): |
| | | from .views import my_view |
| | | request = testing.DummyRequest() |
| | | info = my_view(request) |
| | | self.assertEqual(info.status_int, 500) |
| | | from .views.default import my_view |
| | | info = my_view(dummy_request(self.session)) |
| | | self.assertEqual(info.status_int, 500) |
File was renamed from pyramid/scaffolds/alchemy/+package+/views.py_tmpl |
| | |
| | | |
| | | 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': '{{project}}'} |
| | | |
| | | |
| | | 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: |
| | | |
| | |
| | | After you fix the problem, please restart the Pyramid application to |
| | | try it again. |
| | | """ |
| | | |
| | |
| | | |
| | | requires = [ |
| | | 'pyramid', |
| | | 'pyramid_chameleon', |
| | | 'pyramid_jinja2', |
| | | 'pyramid_debugtoolbar', |
| | | 'pyramid_tm', |
| | | 'SQLAlchemy', |