> I'd just say though that if you need the request and don't have it,
> it's often an indication that the program's structure is wrong.

I authored this change, and you are absolutely correct.  This technique is 
not ideal, but it is designed to stop several anti-patterns that happen 
with great frequency in many SQLAlchemy web integrations in a "less evil" 
but "supported" pattern.

A lot of web implementations will use global variables to access the active 
web request when dealing with "Model" concepts  (examples include 
Flask-SQLAlchemy and legacy Pylons) which is an anti-pattern; a lot of 
Pyramid applications used `get_current_request`, which is explicitly warned 
against.  

In this technique, the "info" dict - which is the official SQLAlchemy place 
for end-users to place data into a session - is used to stash the request.  
It's a bit odd -- the request has a session which has the request - but 
it's the safest way to make the request available to any SQLAlchemy 
object.  (note: this breaks once the session is closed or the object leaves 
the session)  This also makes testing much, much, much easier.

Models shouldn't need to be aware of the context, but sometimes it's the 
best option.  I specifically wrote it so people can  get to the 
`request.registry` to access application settings, like Michael mentioned.  

FWIW, my preferred technique is to structure a SQLAlchemy model independent 
of Pyramid (either as a separate package or part of a larger package at the 
same "level" as the Pyramid app), and have Pyramid/Celery/Commandline-tools 
etc import that model.  Each framework then notes in the "info" dict (i) 
which system SQLAlchemy is being run under and (ii) the current request or 
context. For the sake of simplicity, I left that stuff out of the PR. 

On Sunday, February 21, 2021 at 2:10:13 PM UTC-5 Mike Orr wrote:

> Oh, nifty. And good docstring.
>
> I'd just say though that if you need the request and don't have it,
> it's often an indication that the program's structure is wrong.
> Although there are certainly times when you need something like this,
> such as when you call a third-party function that doesn't take a
> request, then it calls you and you need the request but the caller
> hasn't passed it through.
>
> On Sat, Feb 20, 2021 at 3:42 PM Michael Merickel <mmer...@gmail.com> 
> wrote:
> >
> > It's in the cookiecutter's "get_tm_session" on the master branch. Which 
> is not the default branch.
> >
> > The purpose of the pattern is if your model objects needed access to 
> some settings or some other request properties. It's up to you to decide if 
> that's good or bad. Of course you don't need to use it.
> >
> > - Michael
> >
> > > On Feb 20, 2021, at 17:39, Mike Orr <slugg...@gmail.com> wrote:
> > >
> > > On Sat, Feb 20, 2021 at 12:57 PM Michael Merickel <mmer...@gmail.com> 
> wrote:
> > >> Check out the new pattern of storing the request in the SQLAlchemy 
> session object for easier access in your model layer without threadlocals!
> > >
> > > Where is that? I don't see it in 'pyramid-cookiecutter-starter' or the 
> 2.0 docs.
> > >
> > > I do essentially the opposite. I have a request subclass with reified
> > > methods for external resources like 'request.sa_session()'.
> > > Cookiecutter is still using this concept although using
> > > 'config.add_request_method()' instead of a subclass:
> > >
> > > 
> https://github.com/Pylons/pyramid-cookiecutter-starter/blob/latest/%7B%7Bcookiecutter.repo_name%7D%7D/%7B%7Bcookiecutter.repo_name%7D%7D/sqlalchemy_models/__init__.py
> > > (Lines 71-75.)
> > >
> > > My model classes used to have querying methods but I moved away from
> > > that because they ended up putting too much into the models and being
> > > too limiting (my querying needs inevitably expanded beyond the method
> > > arguments). I now have just the columns and relations in the models,
> > > and separate lib modules for high-level queries. These take a session
> > > argument. I don't usually need a request argument except occasionally
> > > for URL generation. For that I have a postprocessing function that
> > > adds the URL attributes to the query results. For instance:
> > >
> > > # View
> > > results = myapp.lib.mysearch.do_search(sa_session, ...criteria..)
> > > # Return list of ORM objects,
> > > postprocess(results, request)
> > > # Iterate through objects, adding URL attributes for HTML links,
> > > # formatting dates, calculating display values, etc.
> > >
> > > --
> > > 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-discus...@googlegroups.com.
> > > To view this discussion on the web visit 
> https://groups.google.com/d/msgid/pylons-discuss/CAH9f%3Duo821nzLFSttTcvn5xBqbAL2hisuQWUE_%2BCS8q15zUgRA%40mail.gmail.com
> .
> >
> > --
> > 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-discus...@googlegroups.com.
> > To view this discussion on the web visit 
> https://groups.google.com/d/msgid/pylons-discuss/AE3A3A43-AECE-49D5-BB83-AAC8A3DC0798%40gmail.com
> .
>
>
>
> -- 
> Mike Orr <slugg...@gmail.com>
>

-- 
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/5164132f-9e79-40de-aa7a-6e297915db38n%40googlegroups.com.

Reply via email to