<div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><br></div></div></div><div class="gmail_quote"><div dir="ltr">On Mon, Sep 3, 2018 at 3:25 AM Jacco van Dorp <<a href="mailto:j.van.dorp@deonet.nl">j.van.dorp@deonet.nl</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr">This feels really useful to me to make some quick changes to a database - perhaps a database layer could return an class of type Recordclass, and then you just simply mutate it and shove it back into the database. Pseudocode:<div><br></div><div>record = database.execute("SELECT * FROM mytable WHERE primary_key = 15")</div><div>record.mostRecentLoggedInTime = time.time()</div><div>database.execute(f"UPDATE mytable SET mostRecentLoggedInTime = {record.mostRecentLoggedInTime} WHERE primary_key = {record.primary_key}":)</div><div><br></div><div>Or any smart database wrapper might just go:</div><div><br></div><div>database.updateOrInsert(table = mytable, record = record)</div><div><br></div><div>And be smart enough to figure out that we already have a primary key unequal to some sentinel value like None, and do an update, while it could do an insert if the primary key WAS some kind of sentinel value.</div></div></blockquote><div><br>SQLAlchemy.orm solves for this (with evented objects with evented attributes):<br> </div><div><a href="http://docs.sqlalchemy.org/en/latest/orm/session_state_management.html#session-object-states">http://docs.sqlalchemy.org/en/latest/orm/session_state_management.html#session-object-states</a><br></div><div>- Transient, Pending, Persistent, Deleted, Detached </div><div><div><a href="http://docs.sqlalchemy.org/en/latest/orm/session_api.html#sqlalchemy.orm.attributes.flag_modified">http://docs.sqlalchemy.org/en/latest/orm/session_api.html#sqlalchemy.orm.attributes.flag_modified</a></div><div>- flag_modified isn't necessary in most cases because attribute mutation on mapped classes deriving from Base(declarative_base()) is evented</div><div><a href="http://docs.sqlalchemy.org/en/latest/orm/session_events.html#attribute-change-events">http://docs.sqlalchemy.org/en/latest/orm/session_events.html#attribute-change-events</a></div><div><a href="http://docs.sqlalchemy.org/en/latest/orm/tutorial.html">http://docs.sqlalchemy.org/en/latest/orm/tutorial.html</a><br><br>There are packages for handling attribute states with the Django ORM, as well:</div></div><div><br></div><div>- <a href="https://github.com/romgar/django-dirtyfields">https://github.com/romgar/django-dirtyfields</a></div><div>- <a href="https://github.com/Suor/django-dirty">https://github.com/Suor/django-dirty</a></div><div><br></div><div><br></div><div>What would be the performance impact of instead subclassing from recordclass? IDK.</div><div><br></div><div><br></div><div>pyrsistent.PRecord(PMap) is immutable and supports .attribute access:</div><div><a href="https://github.com/tobgu/pyrsistent#precord">https://github.com/tobgu/pyrsistent#precord</a></div></div></div></div></div></div></div></div></div>