Re: [sqlalchemy] Re: Duplicate `self`, without affecting the original instance in memory…

2018-06-23 Thread Dave von Umlaut
I don't mind using merge()… My problem is that using the code linked above, 
I cannot seem to make it to keep the original `self` (it invariably gets 
replaced by the new persisted object).

I'm happy with a shallow copy of the object (I handle the relationship 
separately). My next plan is literally to duplicate the DB row…

On Saturday, 23 June 2018 02:35:39 UTC+9, Mike Bayer wrote:
>
> There's no shortcut outside of merge () for copying attributes, copies are 
> hard to generalize so you probably want to put copy constructors on your 
> classes if you need to do that often.
>
> On Fri, Jun 22, 2018, 1:24 PM Jonathan Vanasco  > wrote:
>
>>
>> FWIW, i use these methods in my base class to copy the object into a 
>> dict.  
>>
>>
>> def columns_as_dict(self):
>> """
>> Beware: this function will trigger a load of attributes if they 
>> have not been loaded yet.
>> """
>> return dict((col.name, getattr(self, col.name))
>> for col
>> in sqlalchemy.orm.class_mapper(self.__class__).
>> mapped_table.c
>> )
>>
>>
>> def loaded_columns_as_dict(self):
>> """
>> This function will only return the loaded columns as a dict.
>> """
>> _dict = self.__dict__
>> return {col.name: _dict[col.name]
>> for col in sqlalchemy.orm.class_mapper(self.__class__).
>> mapped_table.c
>> if col.name in _dict
>> }
>>
>>
>>
>> -- 
>> 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 post to this group, send email to sqlal...@googlegroups.com 
>> .
>> Visit this group at https://groups.google.com/group/sqlalchemy.
>> For more options, visit https://groups.google.com/d/optout.
>>
>

-- 
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 post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at https://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.


[sqlalchemy] Duplicate `self`, without affecting the original instance in memory…

2018-06-22 Thread Dave von Umlaut
I am trying to make a duplicate (with new PK) of an instance *from within* 
the instance.

All the solutions I have found so far, using `make_transient(self)` or 
`session.merge`, change the original instance in memory, rather than create 
a separate object, and I cannot figure a way to keep the original `self` 
(reloading it does not work either).

PS: I am not trying to get a deep copy (I am handling relationships 
separately), merely a clone of the corresponding DB row… But if possible, 
I'd prefer a solution that stays away from a manual copy of attributes…

Any idea on how to proceed?

-- 
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 post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at https://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.


Re: [sqlalchemy] Using a table alias / defining column_property inside a (virtual) parent class…

2018-05-05 Thread Dave von Umlaut


On Sunday, 6 May 2018 07:27:15 UTC+9, Mike Bayer wrote:
 

> We have examples of this kind of versioning in the docs, and I just 
> took a look and found they needed to be modernized, so I've done that

[...]
>
http://docs.sqlalchemy.org/en/latest/_modules/examples/versioned_rows/versioned_rows_w_versionid.html
>  


Sorry, I completely missed this while looking for possible existing 
SQLAlchemy implementations!

Thanks a lot for updating it. Looks great.

One small thing I noticed in my implementation, is that composite key 
autoincrement unsurprisingly does not work well with MySQL (and I believe I 
also had some unexpected behaviours with sqlite). I solved this by using a 
declared attribute with a custom default query:

@declared_attr
def id(cls):
return Column(Integer, primary_key=True, 
default=select([text('COALESCE(MAX(id), 
0)+1 FROM ' + cls.__tablename__)]).as_scalar())


But this, in turn, meant that `id` appeared after `version` in the table 
declaration, making the composite keys be `(version, id)`, which MySQL 
objected to, when trying to do certain foreign key operations (and does not 
seem a great idea altogether for query optimisation). Best solution seemed 
to add:

@declared_attr
def version(cls):
return Column(Integer, primary_key=True, default=0, autoincrement=
False)


I don't know if there's a simpler/cleaner way to ensure that the composite 
primary is created in the right order and with the right autoincrement 
rules, but this seemed to work on both sqlite and mySQL.

you can of course write that query using query.join() directly but the 
> column_property() can't change the query to have a JOIN in the FROM 
> clause automatically.   persisting the is_current_version value might 
> be overall easier. 


Yes, that's what i've been thinking and so far resisting, out of an 
irrational normalisation fetish. I think I will test how it fares, and 
potentially add a persisted value. 

Thanks a lot for your precious help!
-- 
Dave

-- 
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 post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at https://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.


[sqlalchemy] Using a table alias / defining column_property inside a (virtual) parent class…

2018-05-04 Thread Dave von Umlaut
I am trying to create a generic "versioned" SQLAlchemy table model, from 
which I can derive further models. Among other things, I need a 
*is_latest_version* column property that can be used to create appropriate 
joins… 

Following code works fine:

class Versioned(db.Model):
__abstract__ = True
id = Column(Integer, primary_key=True)
version = Column(Integer, primary_key=True)

class Child(Versioned):
pass

t = aliased(Child, name="t")
Child.is_latest_version =  db.column_property(
select([ Child.version == db.func.max(t.version) ])
.select_from(t)
.where(t.id == Child.id)
)



But I cannot figure any way to move the column property up to the parent 
class. Any variation I attempt, bumps into class mapping issues…

Closest I could think off, would be something like:

class Versioned(db.Model):
__abstract__ = True
id = Column(Integer, primary_key=True)
version = Column(Integer, primary_key=True)

@declared_attr
def is_latest_version(cls):
t = aliased(cls, name="t")
return db.column_property(
select([ cls.version == db.func.max(t.version) ])
.select_from(t)
.where(t.id == cls.id)
)

class Child(Versioned):
pass



But it throws an error:
`sqlalchemy.orm.exc.UnmappedClassError: Class 'app.models.Child' is not 
mapped`

Using quotes does not work either (query is executed with quoted fields as 
literal strings).

Is there any way to achieve this kind of column_property in a virtual class?

Also… Not sure if that's related, but I also seem unable to implement 
*is_latest_version* with a nicer join-based query (I suspect solving my 
Alias issues might help):
… FROM child c1 JOIN child c2 ON c2.id = c1.id AND c2.version > c1.version 
WHERE c2.id IS NULL


Thanks in advance for any help!
-- 
Dave

-- 
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 post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at https://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.