123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596 |
- # -*- coding: utf-8 -*-
- from sqlalchemy import engine_from_config
- from sqlalchemy.event import listen
- from sqlalchemy.orm import sessionmaker
- from sqlalchemy.orm import configure_mappers
- import zope.sqlalchemy
- from .meta import DeclarativeBase
- from tracim_backend.models.revision_protection import prevent_content_revision_delete
- # import or define all models here to ensure they are attached to the
- # Base.metadata prior to any initialization routines
- from tracim_backend.models.auth import User, Group, Permission
- from tracim_backend.models.data import Content, ContentRevisionRO
-
- # 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(expire_on_commit=False)
- 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()
- # FIXME - G.M - 02-05-2018 - Check Zope/Sqlalchemy session conf.
- # We use both keep_session=True for zope and
- # expire_on_commit=False for sessionmaker to keep session alive after
- # commit ( in order to not have trouble like
- # https://github.com/tracim/tracim_backend/issues/52
- # or detached objects problems).
- # These problem happened because we use "commit" in our current code.
- # Understand what those params really mean and check if it can cause
- # troubles somewhere else.
- # see https://stackoverflow.com/questions/16152241/how-to-get-a-sqlalchemy-session-managed-by-zope-transaction-that-has-the-same-sc # nopep8
- zope.sqlalchemy.register(
- dbsession,
- transaction_manager=transaction_manager,
- keep_session=True,
- )
- listen(dbsession, 'before_flush', prevent_content_revision_delete)
- return dbsession
-
-
- def includeme(config):
- """
- Initialize the model for a Pyramid app.
-
- Activate this setup using ``config.include('tracim.models')``.
-
- """
- settings = config.get_settings()
- settings['tm.manager_hook'] = 'pyramid_tm.explicit_manager'
-
- # use pyramid_tm to hook the transaction lifecycle to the request
- config.include('pyramid_tm')
-
- # use pyramid_retry to retry a request when transient exceptions occur
- config.include('pyramid_retry')
-
- 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
- )
|