Re: [sqlalchemy] Injecting User info into _history table to track who performed the change

2021-03-15 Thread 'Jonathan Vanasco' via sqlalchemy
Going beyond what Simon did..

I typically make make a table like `user_transaction`, which has all of the 
relevant information for the transaction:

* User ID
* Timestamp
* Remote IP

Using the sqlalchemy hooks, I'll then do something like:

* update the object table with the user_transaction id
or
* use an association table that tracks a user_transaction_id to an object 
id and version
 
FYI, Simon -- as of a few weeks ago, that pattern is now part of the 
pyramid sqlalchemy starter template!

On Monday, March 15, 2021 at 6:46:02 AM UTC-4 Simon King wrote:

> I use pyramid as a web framework, and when I create the DB session for
> each request, I add a reference to the current request object to the
> DB session. The session object has an "info" attribute which is
> intended for application-specific things like this:
>
>
> https://docs.sqlalchemy.org/en/13/orm/session_api.html#sqlalchemy.orm.session.Session.info
>
> Then, in the before_flush event handler, I retrieve the request object
> from session.info, and then I can add whatever request-specific info I
> want to the DB.
>
> Simon
>
> On Sun, Mar 14, 2021 at 4:05 PM JPLaverdure  wrote:
> >
> > Hi Elmer,
> >
> > Thanks for your reply !
> > My issue is not with obtaining the info I want to inject (the logged in 
> users's email), I already have that all ready to go :)
> >
> > My whole database is versioned using the history_meta.py example from 
> SQLAlchemy
> > 
> https://docs.sqlalchemy.org/en/13/_modules/examples/versioned_history/history_meta.html
> >
> > I was hoping for a simple way to inject the user info into the _history 
> row creation steps.
> >
> > The SQLAlchemy example makes use of this event listener:
> >
> > def versioned_session(session):
> >
> > @event.listens_for(session, "before_flush")
> > def before_flush(session, flush_context, instances):
> > for obj in versioned_objects(session.dirty):
> > create_version(obj, session)
> > for obj in versioned_objects(session.deleted):
> > create_version(obj, session, deleted=True)
> >
> > So I'm tempted to follow the same strategy and just override this 
> listener to supplement it with the user info but I'm wondering how to pass 
> in non SQLAlchemy info into its execution context...
> >
> > So basically, I have the info I want to inject, I'm just not sure how to 
> pass it to SQLAlchemy
> >
> > Thanks,
> >
> > JP
> >
> > On Friday, March 12, 2021 at 6:55:19 p.m. UTC-5 elmer@gmail.com 
> wrote:
> >>
> >> Hi JP,
> >>
> >> Depending on how you've implemented your history tracking, that routine 
> is quite far removed from your web framework and getting a neat, clean way 
> of dealing with that might not be within reach.
> >>
> >> However, most web frameworks have some concept of a threadlocal request 
> (or function to retrieve it), which you could invoke and if such a request 
> exists, you could use that to load whatever user identity you have 
> available on there (again, the details differ, but this tends to be a 
> shared feature). From there you can store the user either as a foreign key, 
> or a unique identifier like email. Which one you pick would depend on how 
> you want the history to be affected when you delete a user record for 
> example.
> >>
> >>
> >>
> >> On Fri, Mar 12, 2021 at 11:58 PM JPLaverdure  
> wrote:
> >>>
> >>> Hello everyone,
> >>>
> >>> We already have the ability to timestamp the creation of the history 
> row, but it would also be interesting to be able to track the user 
> responsible for the content update.
> >>> I would like to get suggestions on the best way to achieve this.
> >>>
> >>> I realize this is somewhat outside the scope of sqlalchemy as the 
> notion of a "logged in user" is more closely related to the context of the 
> app/webapp using SQLAlchemy as its ORM but maybe other people would benefit 
> from having a way to inject arbitrary data in the history table.
> >>>
> >>> Ideally, I would like the insert in the _history table to be atomic, 
> so I feel like hooking an update statement to an event might not be the way 
> to go.
> >>> I'm tempted to modify the signature of before_flush but I'm not sure 
> where it gets called.
> >>>
> >>> Any help is welcome !
> >>> Thanks
> >>>
> >>> JP
> >>>
> >>> --
> >>> SQLAlchemy -
> >>> The Python SQL Toolkit and Object Relational Mapper
> >>>
> >>> http://www.sqlalchemy.org/
> >>>
> >>> To post example code, please provide an MCVE: Minimal, Complete, and 
> Verifiable Example. See http://stackoverflow.com/help/mcve for a full 
> description.
> >>> ---
> >>> You received this message because you are subscribed to the Google 
> Groups "sqlalchemy" group.
> >>> To unsubscribe from this group and stop receiving emails from it, send 
> an email to sqlalchemy+...@googlegroups.com.
> >>> To view this discussion on the web visit 
> https://groups.google.com/d/msgid/sqlalchemy/82a24998-14e1-4ff4-a725-dd25c20a8bf2n%40googlegroups.com
> .
> >>
> >>
> >>
> >> --
> >>
> >> Elmer
> >
> > --
> > SQLAlchemy -
> > The 

Re: [sqlalchemy] Injecting User info into _history table to track who performed the change

2021-03-15 Thread Jean-Philippe Laverdure
Ohhh, that sounds perfect !
And since I already make use of class based views, that should be dead
simple to put in place.

Thanks for the support, guys

Cheers,
JP

On Mon, 15 Mar 2021 at 06:46, Simon King  wrote:

> I use pyramid as a web framework, and when I create the DB session for
> each request, I add a reference to the current request object to the
> DB session. The session object has an "info" attribute which is
> intended for application-specific things like this:
>
>
> https://docs.sqlalchemy.org/en/13/orm/session_api.html#sqlalchemy.orm.session.Session.info
>
> Then, in the before_flush event handler, I retrieve the request object
> from session.info, and then I can add whatever request-specific info I
> want to the DB.
>
> Simon
>
> On Sun, Mar 14, 2021 at 4:05 PM JPLaverdure 
> wrote:
> >
> > Hi Elmer,
> >
> > Thanks for your reply !
> > My issue is not with obtaining the info I want to inject (the logged in
> users's email), I already have that all ready to go :)
> >
> > My whole database is versioned using the history_meta.py example from
> SQLAlchemy
> >
> https://docs.sqlalchemy.org/en/13/_modules/examples/versioned_history/history_meta.html
> >
> > I was hoping for a simple way to inject the user info into the _history
> row creation steps.
> >
> > The SQLAlchemy example makes use of this event listener:
> >
> > def versioned_session(session):
> >
> > @event.listens_for(session, "before_flush")
> > def before_flush(session, flush_context, instances):
> > for obj in versioned_objects(session.dirty):
> > create_version(obj, session)
> >for obj in versioned_objects(session.deleted):
> > create_version(obj, session, deleted=True)
> >
> > So I'm tempted to follow the same strategy and just override this
> listener to supplement it with the user info but I'm wondering how to pass
> in non SQLAlchemy info into its execution context...
> >
> > So basically, I have the info I want to inject, I'm just not sure how to
> pass it to SQLAlchemy
> >
> > Thanks,
> >
> > JP
> >
> > On Friday, March 12, 2021 at 6:55:19 p.m. UTC-5 elmer@gmail.com
> wrote:
> >>
> >> Hi JP,
> >>
> >> Depending on how you've implemented your history tracking, that routine
> is quite far removed from your web framework and getting a neat, clean way
> of dealing with that might not be within reach.
> >>
> >> However, most web frameworks have some concept of a threadlocal request
> (or function to retrieve it), which you could invoke and if such a request
> exists, you could use that to load whatever user identity you have
> available on there (again, the details differ, but this tends to be a
> shared feature). From there you can store the user either as a foreign key,
> or a unique identifier like email. Which one you pick would depend on how
> you want the history to be affected when you delete a user record for
> example.
> >>
> >>
> >>
> >> On Fri, Mar 12, 2021 at 11:58 PM JPLaverdure 
> wrote:
> >>>
> >>> Hello everyone,
> >>>
> >>> We already have the ability to timestamp the creation of the history
> row, but it would also be interesting to be able to track the user
> responsible for the content update.
> >>> I would like to get suggestions on the best way to achieve this.
> >>>
> >>> I realize this is somewhat outside the scope of sqlalchemy as the
> notion of a "logged in user" is more closely related to the context of the
> app/webapp using SQLAlchemy as its ORM but maybe other people would benefit
> from having a way to inject arbitrary data in the history table.
> >>>
> >>> Ideally, I would like the insert in the _history table to be atomic,
> so I feel like hooking an update statement to an event might not be the way
> to go.
> >>> I'm tempted to modify the signature of before_flush but I'm not sure
> where it gets called.
> >>>
> >>> Any help is welcome !
> >>> Thanks
> >>>
> >>> JP
> >>>
> >>> --
> >>> SQLAlchemy -
> >>> The Python SQL Toolkit and Object Relational Mapper
> >>>
> >>> http://www.sqlalchemy.org/
> >>>
> >>> To post example code, please provide an MCVE: Minimal, Complete, and
> Verifiable Example. See http://stackoverflow.com/help/mcve for a full
> description.
> >>> ---
> >>> You received this message because you are subscribed to the Google
> Groups "sqlalchemy" group.
> >>> To unsubscribe from this group and stop receiving emails from it, send
> an email to sqlalchemy+...@googlegroups.com.
> >>> To view this discussion on the web visit
> https://groups.google.com/d/msgid/sqlalchemy/82a24998-14e1-4ff4-a725-dd25c20a8bf2n%40googlegroups.com
> .
> >>
> >>
> >>
> >> --
> >>
> >> Elmer
> >
> > --
> > SQLAlchemy -
> > The Python SQL Toolkit and Object Relational Mapper
> >
> > http://www.sqlalchemy.org/
> >
> > To post example code, please provide an MCVE: Minimal, Complete, and
> Verifiable Example. See http://stackoverflow.com/help/mcve for a full
> description.
> > ---
> > You received this message because you are subscribed to the Google
> Groups 

Re: [sqlalchemy] Using Abstract Base Classes with ORM Table Classes

2021-03-15 Thread Mike Bayer
you no longer have to use DeclarativeMeta at all, you can use a class decorator:

https://docs.sqlalchemy.org/en/14/orm/mapping_styles.html#declarative-mapping-using-a-decorator-no-declarative-base


if you are on 1.3, there's a way to get the same effect in 1.3 using the 
instrument_declarative function:  
https://docs.sqlalchemy.org/en/13/orm/extensions/declarative/api.html?highlight=instrument_declarative#sqlalchemy.ext.declarative.instrument_declarative


which can be turned into an equivalent decorator.

that said I have not yet experimented with mapping classes that are also 
extending ABCMeta so I'm not sure if there are other issues.



On Sun, Mar 14, 2021, at 8:53 PM, Richard Damon wrote:
> I have a lot of tables that have some similar functionality that I would
> like to factor out into a base mix-in class that provides some common
> methods. Some of these methods will want to use a method that must be
> defined in the actual table ORM class, and would be an abstract method
> in the base. If you just blindly do this you get the Python error of
> multiple metaclasses, so I need to define a metaclass that inherets from
> both ABCMeta and DeclarativeMeta, and then the Table ORM classes need to
> mention declarative_base, the mixin and metaclass=mymeta. This works but
> looks wordy.
> 
> If instead I try to put the mix-in between declarative_base and the
> table class in the heirarchy, SQLAlchemy complains that it is missing
> information for it to be a table (which is correct). If I put it as a
> base to declarative_base the SQLAlchemy gets errors that it needs to
> implement the abstract methods (and I of course can only do this once).
> 
> I could make the mixin not use the ABCMeta as its metaclass, but then if
> I forget to define the abstract method in the table, I get no
> complaints, at best I could catch the call to the abstract method
> because it wasn't overridden.
> 
> Is this the way it is supposed to work, or am I missing some other trick?
> 
> Side question, when doing this sort of mix-in, does the order of the
> mix-in and declarative_base matter, or is there a real preference?
> 
> -- 
> Richard Damon
> 
> -- 
> SQLAlchemy - 
> The Python SQL Toolkit and Object Relational Mapper
> 
> http://www.sqlalchemy.org/
> 
> To post example code, please provide an MCVE: Minimal, Complete, and 
> Verifiable Example.  See  http://stackoverflow.com/help/mcve for a full 
> description.
> --- 
> You received this message because you are subscribed to the Google Groups 
> "sqlalchemy" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to sqlalchemy+unsubscr...@googlegroups.com.
> To view this discussion on the web visit 
> https://groups.google.com/d/msgid/sqlalchemy/e8d4c401-95fe-957f-7d65-3e37cd5150c6%40Damon-Family.org.
> 

-- 
SQLAlchemy - 
The Python SQL Toolkit and Object Relational Mapper

http://www.sqlalchemy.org/

To post example code, please provide an MCVE: Minimal, Complete, and Verifiable 
Example.  See  http://stackoverflow.com/help/mcve for a full description.
--- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/sqlalchemy/1f4f4ffc-d7dc-4ead-b031-a1e77c13586a%40www.fastmail.com.


Re: [sqlalchemy] Injecting User info into _history table to track who performed the change

2021-03-15 Thread Simon King
I use pyramid as a web framework, and when I create the DB session for
each request, I add a reference to the current request object to the
DB session. The session object has an "info" attribute which is
intended for application-specific things like this:

https://docs.sqlalchemy.org/en/13/orm/session_api.html#sqlalchemy.orm.session.Session.info

Then, in the before_flush event handler, I retrieve the request object
from session.info, and then I can add whatever request-specific info I
want to the DB.

Simon

On Sun, Mar 14, 2021 at 4:05 PM JPLaverdure  wrote:
>
> Hi Elmer,
>
> Thanks for your reply !
> My issue is not with obtaining the info I want to inject (the logged in 
> users's email), I already have that all ready to go :)
>
> My whole database is versioned using the history_meta.py example from 
> SQLAlchemy
> https://docs.sqlalchemy.org/en/13/_modules/examples/versioned_history/history_meta.html
>
> I was hoping for a simple way to inject the user info into the _history row 
> creation steps.
>
> The SQLAlchemy example makes use of this event listener:
>
> def versioned_session(session):
>
> @event.listens_for(session, "before_flush")
> def before_flush(session, flush_context, instances):
> for obj in versioned_objects(session.dirty):
> create_version(obj, session)
>for obj in versioned_objects(session.deleted):
> create_version(obj, session, deleted=True)
>
> So I'm tempted to follow the same strategy and just override this listener to 
> supplement it with the user info but I'm wondering how to pass in non 
> SQLAlchemy info into its execution context...
>
> So basically, I have the info I want to inject, I'm just not sure how to pass 
> it to SQLAlchemy
>
> Thanks,
>
> JP
>
> On Friday, March 12, 2021 at 6:55:19 p.m. UTC-5 elmer@gmail.com wrote:
>>
>> Hi JP,
>>
>> Depending on how you've implemented your history tracking, that routine is 
>> quite far removed from your web framework and getting a neat, clean way of 
>> dealing with that might not be within reach.
>>
>> However, most web frameworks have some concept of a threadlocal request (or 
>> function to retrieve it), which you could invoke and if such a request 
>> exists, you could use that to load whatever user identity you have available 
>> on there (again, the details differ, but this tends to be a shared feature). 
>> From there you can store the user either as a foreign key, or a unique 
>> identifier like email. Which one you pick would depend on how you want the 
>> history to be affected when you delete a user record for example.
>>
>>
>>
>> On Fri, Mar 12, 2021 at 11:58 PM JPLaverdure  wrote:
>>>
>>> Hello everyone,
>>>
>>> We already have the ability to timestamp the creation of the history row, 
>>> but it would also be interesting to be able to track the user responsible 
>>> for the content update.
>>> I would like to get suggestions on the best way to achieve this.
>>>
>>> I realize this is somewhat outside the scope of sqlalchemy as the notion of 
>>> a "logged in user" is more closely related to the context of the app/webapp 
>>> using SQLAlchemy as its ORM but maybe other people would benefit from 
>>> having a way to inject arbitrary data in the history table.
>>>
>>> Ideally, I would like the insert in the _history table to be atomic, so I 
>>> feel like hooking an update statement to an event might not be the way to 
>>> go.
>>> I'm tempted to modify the signature of before_flush but I'm not sure where 
>>> it gets called.
>>>
>>> Any help is welcome !
>>> Thanks
>>>
>>> JP
>>>
>>> --
>>> SQLAlchemy -
>>> The Python SQL Toolkit and Object Relational Mapper
>>>
>>> http://www.sqlalchemy.org/
>>>
>>> To post example code, please provide an MCVE: Minimal, Complete, and 
>>> Verifiable Example. See http://stackoverflow.com/help/mcve for a full 
>>> description.
>>> ---
>>> You received this message because you are subscribed to the Google Groups 
>>> "sqlalchemy" group.
>>> To unsubscribe from this group and stop receiving emails from it, send an 
>>> email to sqlalchemy+...@googlegroups.com.
>>> To view this discussion on the web visit 
>>> https://groups.google.com/d/msgid/sqlalchemy/82a24998-14e1-4ff4-a725-dd25c20a8bf2n%40googlegroups.com.
>>
>>
>>
>> --
>>
>> Elmer
>
> --
> SQLAlchemy -
> The Python SQL Toolkit and Object Relational Mapper
>
> http://www.sqlalchemy.org/
>
> To post example code, please provide an MCVE: Minimal, Complete, and 
> Verifiable Example. See http://stackoverflow.com/help/mcve for a full 
> description.
> ---
> You received this message because you are subscribed to the Google Groups 
> "sqlalchemy" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to sqlalchemy+unsubscr...@googlegroups.com.
> To view this discussion on the web visit 
> https://groups.google.com/d/msgid/sqlalchemy/58bb6713-18f4-4d69-8d7b-a27772711bd5n%40googlegroups.com.

-- 
SQLAlchemy - 
The Python SQL Toolkit and Object 

Re: [sqlalchemy] Create Sqlalchemy ORM class from regular class gets "has no attribute ''_sa_instance_state''"

2021-03-15 Thread Simon King
I haven't followed your code in detail, but I think the problem might be here:

clazz = school.Class('12', 'A')

students = [
Student("Name1", "Sname1", clazz=clazz, code='aa7'),
Student("Name2", "Sname2", clazz=clazz, code='bb7'),
Student("Name3", "Sname3", clazz=clazz, code='cc7')
]

You are creating an instance of "school.Class", which is the
non-sqlalchemy base class. You probably meant to create an instance of
"Class", which is the SQLAlchemy-mapped subclass, didn't you?

Simon

On Fri, Mar 12, 2021 at 11:10 AM ScottBot  wrote:
>
> I have a game that I am coding for school (not a project or homework) and I 
> am trying to use a SQLite database with sqlalchemy to store the game info. I 
> don't know what the problem is or how I can fix it. Any help is appreciated.
> https://stackoverflow.com/questions/66591466/sqlalchemy-orm-from-regular-class
>
> --
> SQLAlchemy -
> The Python SQL Toolkit and Object Relational Mapper
>
> http://www.sqlalchemy.org/
>
> To post example code, please provide an MCVE: Minimal, Complete, and 
> Verifiable Example. See http://stackoverflow.com/help/mcve for a full 
> description.
> ---
> You received this message because you are subscribed to the Google Groups 
> "sqlalchemy" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to sqlalchemy+unsubscr...@googlegroups.com.
> To view this discussion on the web visit 
> https://groups.google.com/d/msgid/sqlalchemy/b3e6fb67-6cab-4484-8c39-a01999640e67n%40googlegroups.com.

-- 
SQLAlchemy - 
The Python SQL Toolkit and Object Relational Mapper

http://www.sqlalchemy.org/

To post example code, please provide an MCVE: Minimal, Complete, and Verifiable 
Example.  See  http://stackoverflow.com/help/mcve for a full description.
--- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/sqlalchemy/CAFHwexcFYWK7yu9hW42LgUDB3LL%2BFAuCJqogpvYDjBe1MHigNQ%40mail.gmail.com.


Re: [sqlalchemy] SQLAlchemy database record created on import of module

2021-03-15 Thread Simon King
I suggest you set up an event listener for the "after_attach" event on
your session:

https://docs.sqlalchemy.org/en/13/orm/events.html#sqlalchemy.orm.events.SessionEvents.after_attach

Then you can set a breakpoint in the listener (or raise an exception,
or use the traceback module to print a stack trace) to find out where
in your code you are adding this object to the session.

Hope that helps,

Simon

On Fri, Mar 12, 2021 at 4:17 AM Advanced Spectrum
 wrote:
>
> I have a Base class like this:
>
> class FlagTable(Base):
>
> __tablename__ = "FLAG_TABLE"
>
> FLAG_TABLE_ID = Column(Integer, primary_key=True, autoincrement="auto")
> COLUMN_1 = Column(Boolean)
> COLUMN_2 = Column(Boolean)
> COLUMN_3 = Column(Boolean)
>
> I have a Python function in 'FlagTable.py' that would create a record with 
> the ORM FlagTable object:
>
> from FlagTable import FlagTable
>
> def addFlagsToFlagTable(arg1, arg2, arg3):
>
> myFlags= FlagTable(COLUMN_1=arg1, COLUMN_2=arg1, COLUMN_3=arg1)
> session.add(myFlags)
> session.commit()
>
> #main code starts here
> callFunc = addFlagsToFlagTable(true, false, false)
>
>
> When I step through the code in debugger mode I see that the record I want to 
> add to my postgres database table gets added at the time of the import. It 
> does not even wait for when the addFlagsToFlagTable function gets called in 
> my main code. My *'Base = declarative_base()'* statement is in another class 
> which is related to FlagTable class. Can someone educate me a bit on what is 
> going on?
>
> --
> SQLAlchemy -
> The Python SQL Toolkit and Object Relational Mapper
>
> http://www.sqlalchemy.org/
>
> To post example code, please provide an MCVE: Minimal, Complete, and 
> Verifiable Example. See http://stackoverflow.com/help/mcve for a full 
> description.
> ---
> You received this message because you are subscribed to the Google Groups 
> "sqlalchemy" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to sqlalchemy+unsubscr...@googlegroups.com.
> To view this discussion on the web visit 
> https://groups.google.com/d/msgid/sqlalchemy/7306a853-4017-4018-bc13-fa01aa8bb5adn%40googlegroups.com.

-- 
SQLAlchemy - 
The Python SQL Toolkit and Object Relational Mapper

http://www.sqlalchemy.org/

To post example code, please provide an MCVE: Minimal, Complete, and Verifiable 
Example.  See  http://stackoverflow.com/help/mcve for a full description.
--- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/sqlalchemy/CAFHwexc6Wqeyf5w8CPsrm_jK_YJgV6au7UUQ-2fxxzHja6QQSg%40mail.gmail.com.