This is insanely helpful - thank you Michael.  I'm going to pass the 
dbsession into the class method for now but look into a service layer.  

On Monday, January 6, 2020 at 2:56:28 PM UTC-6, Michael Merickel wrote:
>
> This is a super common complaint from people and it doesn't have a single 
> definitive solution. There are a couple handy tricks:
>
> 1. If your classmethod receives any managed objects, you can get a 
> reference to the session from the object itself. For example 
> ``sqlalchemy.orm.object_session(user)``.
>
> 2. The easy answer when the above doesn't work is to pass the dbsession 
> into the class method.
>
> After this - if still not satisfied - are some hacky things you can do:
>
> 1. Stop using classmethod approaches and instead put in a real service 
> layer. This has tons of benefits, see something like pyramid_services for 
> more information about this. This approach will allow you to bind the whole 
> service to a dbsession, and no longer need to pass it around at all.
>
> 2. Define a helper to grab the session from the request threadlocal. 
> Something like ``get_current_dbsession = lambda: 
> get_current_request().dbsession``. Then import that and use it via 
> ``dbsession = get_current_dbsession()``.
>
> The threadlocal approach above has some downsides but is still better than 
> using a scoped session. Allowing the request to seep into and infect your 
> data model is a little wonky and makes your model code less reusable 
> outside of Pyramid. Even if you are okay with that, something like 
> ``get_current_dbsession().query()`` is going to be better than 
> ``scoped_session.query()`` because it's more explicitly a value that 
> changes over time versus the magic scoped session object proxy.
>
> In my own apps I use all the approaches mentioned above except the 
> threadlocal one.
>
> - Michael
>
> On Mon, Jan 6, 2020 at 2:37 PM Kate Boelhauf <ka...@katimari.com 
> <javascript:>> wrote:
>
>> A little background - I'm updating my entire site and used a cookiecutter 
>> as referenced in Pyramids docs to do so. I am using sqlalchemy.
>>
>> It has a db session as a request method. This works perfectly for me in 
>> all of my views. However, I have class methods in my models that need to 
>> access a session.  I can't figure out a way to access the session that the 
>> cookiecutter set up in models.py so I reverted to creating a separate 
>> session using  
>> scoped_session(sessionmaker(extension=ZopeTransactionExtension())) and 
>> importing it into my model and using the request session in my views.
>>
>> This just seems wrong - am I approaching this wrong?
>>
>> Below is the model.py file that the cookiecutter created:
>>
>> from sqlalchemy import engine_from_config
>> from sqlalchemy.orm import sessionmaker
>> from sqlalchemy.orm import configure_mappers
>> 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 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('tutorial.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
>>     )
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>> -- 
>> You received this message because you are subscribed to the Google Groups 
>> "pylons-discuss" group.
>> To unsubscribe from this group and stop receiving emails from it, send an 
>> email to pylons-...@googlegroups.com <javascript:>.
>> To view this discussion on the web visit 
>> https://groups.google.com/d/msgid/pylons-discuss/c60ba3e3-d3ea-4f59-9c94-460c7964c865%40googlegroups.com
>>  
>> <https://groups.google.com/d/msgid/pylons-discuss/c60ba3e3-d3ea-4f59-9c94-460c7964c865%40googlegroups.com?utm_medium=email&utm_source=footer>
>> .
>>
>
>
> -- 
>
> Michael
>

-- 
You received this message because you are subscribed to the Google Groups 
"pylons-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to pylons-discuss+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/pylons-discuss/f1e08a09-0d14-49a5-8652-e47027965234%40googlegroups.com.

Reply via email to