[sqlalchemy] Polymorphic concrete inheritance question
Hello all, I've been playing a bit with polymorphic concrete inheritance, and noticed that when you have several levels of polymorphic loading (ie my child class is also a parent class which I want to load polymorphically), the query for the top-level class includes the child polymorphic join while I don't see any reason to (its table is already contained in the parent join). See attached example. class A(object): ... class B(A): pass class C(B): pass The query ends up something like: SELECT [all_columns] FROM ([pjoin_abc]), ([pjoin_bc]) Am I using it wrong, or is this a bug? -- Gaëtan de Menten http://openhex.org --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups sqlalchemy group. To post to this group, send email to sqlalchemy@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en -~--~~~~--~~--~--~--- from sqlalchemy import * from sqlalchemy.orm import * metadata = MetaData() metadata.bind = 'sqlite:///' a_table = Table('a', metadata, Column('id', Integer, primary_key=True), Column('data1', String(20)) ) b_table = Table('b', metadata, Column('id', Integer, primary_key=True), Column('data1', String(20)), Column('data2', String(20)) ) c_table = Table('c', metadata, Column('id', Integer, primary_key=True), Column('data1', String(20)), Column('data2', String(20)), Column('data3', String(20)) ) metadata.create_all() class A(object): def __init__(self, **kwargs): for k, v in kwargs.iteritems(): setattr(self, k, v) class B(A): pass class C(B): pass pjoin_all = polymorphic_union({ 'a': a_table, 'b': b_table, 'c': c_table }, 'type', 'pjoin') pjoin_bc = polymorphic_union({ 'b': b_table, 'c': c_table }, 'type', 'pjoin_bc') a_m = mapper(A, a_table, with_polymorphic=('*', pjoin_all), polymorphic_on=pjoin_all.c.type, polymorphic_identity='a') b_m = mapper(B, b_table, inherits=a_m, concrete=True, with_polymorphic=('*', pjoin_bc), polymorphic_on=pjoin_bc.c.type, polymorphic_identity='b') c_m = mapper(C, c_table, inherits=b_m, concrete=True, polymorphic_identity='c') Session = sessionmaker() session = Session() a1 = A(data1='a1') b1 = B(data1='b1', data2='b1') c1 = C(data1='c1', data2='c1', data3='c1') session.add(a1) session.add(b1) session.add(c1) session.commit() metadata.bind.echo = True session.query(A).all() print * * 20, B, * * 20 session.query(B).all()
[sqlalchemy] Re: Polymorphic concrete inheritance question
hm i had not run my tests for quite a while.. this seems recent thing. lets see if i can dig anything of help... nothing much, one side works, another not at all. one of my set of inheritance tests (direct over sa, A-B) is ok. the other one (over dbcook) fails completely, even for A-B inheritance. But they seem same as mapping... there's something really subtle. i either get a sort of decart product, or empty result. and also i stepped on this: File sqlalchemy/orm/mapper.py, line 168, in __init__ self.with_polymorphic[1] = self.with_polymorphic[1].alias() TypeError: 'tuple' object does not support item assignment ciao svil On Wednesday 03 December 2008 11:06:24 Gaetan de Menten wrote: Hello all, I've been playing a bit with polymorphic concrete inheritance, and noticed that when you have several levels of polymorphic loading (ie my child class is also a parent class which I want to load polymorphically), the query for the top-level class includes the child polymorphic join while I don't see any reason to (its table is already contained in the parent join). See attached example. class A(object): ... class B(A): pass class C(B): pass The query ends up something like: SELECT [all_columns] FROM ([pjoin_abc]), ([pjoin_bc]) Am I using it wrong, or is this a bug? --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups sqlalchemy group. To post to this group, send email to sqlalchemy@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en -~--~~~~--~~--~--~---
[sqlalchemy] Re: inferring object class/table directly
On Tue, 2 Dec 2008 at 23:21, Faheem Mitha wrote: Yes, I was looking for this, and printed out obj.__dict__ but didn't see it there. A dictionary of attributes is very useful in theory, but doesn't always seem to have all attributes. Is this documented anywhere? Try dir(obj). You'll see it there. The __dict__ is only for instance attributes. Not too difficult. You can also use type(obj) instead of obj.__class__. I thought of trying this, but didn't. It didn't seem likely to work, anyway. Is either of these preferred over the other in terms of API stability, and if so, why? obj.__class__ is a python thing, as is type(obj), and neither of those is changing in python 3.0, so I'd think both would be stable API wise :) However, the documentation of __class__ makes it clear you get the class back, while the documentation of the 'type' built in function does not...so I'd lean toward using __class__, myself. It also means you'll get an earlier error if you accidentally pass something that is not actually a class instance into your function. --RDM --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups sqlalchemy group. To post to this group, send email to sqlalchemy@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en -~--~~~~--~~--~--~---
[sqlalchemy] Re: Polymorphic concrete inheritance question
um yeah, actually this behavior is affecting all multi-level usage of polymorphic_union. So, while polymorphic_union is quite obviously (since nobody has noticed this pretty glaring issue) on the decline in the 0.5 series, this is quite severe and ill try to have a look at it today. On Dec 3, 2008, at 4:06 AM, Gaetan de Menten wrote: Hello all, I've been playing a bit with polymorphic concrete inheritance, and noticed that when you have several levels of polymorphic loading (ie my child class is also a parent class which I want to load polymorphically), the query for the top-level class includes the child polymorphic join while I don't see any reason to (its table is already contained in the parent join). See attached example. class A(object): ... class B(A): pass class C(B): pass The query ends up something like: SELECT [all_columns] FROM ([pjoin_abc]), ([pjoin_bc]) Am I using it wrong, or is this a bug? -- Gaëtan de Menten http://openhex.org from sqlalchemy import * from sqlalchemy.orm import * metadata = MetaData() metadata.bind = 'sqlite:///' a_table = Table('a', metadata, Column('id', Integer, primary_key=True), Column('data1', String(20)) ) b_table = Table('b', metadata, Column('id', Integer, primary_key=True), Column('data1', String(20)), Column('data2', String(20)) ) c_table = Table('c', metadata, Column('id', Integer, primary_key=True), Column('data1', String(20)), Column('data2', String(20)), Column('data3', String(20)) ) metadata.create_all() class A(object): def __init__(self, **kwargs): for k, v in kwargs.iteritems(): setattr(self, k, v) class B(A): pass class C(B): pass pjoin_all = polymorphic_union({ 'a': a_table, 'b': b_table, 'c': c_table }, 'type', 'pjoin') pjoin_bc = polymorphic_union({ 'b': b_table, 'c': c_table }, 'type', 'pjoin_bc') a_m = mapper(A, a_table, with_polymorphic=('*', pjoin_all), polymorphic_on=pjoin_all.c.type, polymorphic_identity='a') b_m = mapper(B, b_table, inherits=a_m, concrete=True, with_polymorphic=('*', pjoin_bc), polymorphic_on=pjoin_bc.c.type, polymorphic_identity='b') c_m = mapper(C, c_table, inherits=b_m, concrete=True, polymorphic_identity='c') Session = sessionmaker() session = Session() a1 = A(data1='a1') b1 = B(data1='b1', data2='b1') c1 = C(data1='c1', data2='c1', data3='c1') session.add(a1) session.add(b1) session.add(c1) session.commit() metadata.bind.echo = True session.query(A).all() print * * 20, B, * * 20 session.query(B).all() --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups sqlalchemy group. To post to this group, send email to sqlalchemy@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en -~--~~~~--~~--~--~---
[sqlalchemy] Re: Polymorphic concrete inheritance question
On Wed, Dec 3, 2008 at 15:03, Michael Bayer [EMAIL PROTECTED] wrote: um yeah, actually this behavior is affecting all multi-level usage of polymorphic_union. So, while polymorphic_union is quite obviously (since nobody has noticed this pretty glaring issue) on the decline in the 0.5 series, this is quite severe and ill try to have a look at it today. Do you want a bug report for this? -- Gaëtan de Menten http://openhex.org --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups sqlalchemy group. To post to this group, send email to sqlalchemy@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en -~--~~~~--~~--~--~---
[sqlalchemy] Re: Polymorphic concrete inheritance question
this ones big, i can handle it. the attached patch makes your case work, but the problem represented here still makes itself apparent in other ways and I havent strength tested this patch. you might want to see if this patch works in all of your test cases. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups sqlalchemy group. To post to this group, send email to sqlalchemy@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en -~--~~~~--~~--~--~--- Index: lib/sqlalchemy/orm/query.py === --- lib/sqlalchemy/orm/query.py (revision 5405) +++ lib/sqlalchemy/orm/query.py (working copy) @@ -1647,7 +1647,8 @@ self.entities = [entity] self.entity_zero = entity - +self._has_polymorphic_selectable = False + def setup_entity(self, entity, mapper, adapter, from_obj, is_aliased_class, with_polymorphic): self.mapper = mapper self.extension = self.mapper.extension @@ -1668,6 +1669,7 @@ mappers, from_obj = self.mapper._with_polymorphic_args(cls_or_mappers, selectable) self._with_polymorphic = mappers +self._has_polymorphic_selectable = bool(from_obj) # TODO: do the wrapped thing here too so that with_polymorphic() can be # applied to aliases @@ -1748,7 +1750,7 @@ if adapter: context.order_by = adapter.adapt_list(util.to_list(context.order_by)) -for value in self.mapper._iterate_polymorphic_properties(self._with_polymorphic): +for value in self.mapper._iterate_polymorphic_properties(self._with_polymorphic, self._has_polymorphic_selectable): if query._only_load_props and value.key not in query._only_load_props: continue value.setup( Index: lib/sqlalchemy/orm/mapper.py === --- lib/sqlalchemy/orm/mapper.py(revision 5406) +++ lib/sqlalchemy/orm/mapper.py(working copy) @@ -862,18 +862,20 @@ @property def _default_polymorphic_properties(self): -return util.unique_list( +return iter(util.unique_list( chain(*[list(mapper.iterate_properties) for mapper in [self] + self._with_polymorphic_mappers]) -) - -def _iterate_polymorphic_properties(self, mappers=None): -if mappers is None: -return iter(self._default_polymorphic_properties) +)) + +def _iterate_polymorphic_properties(self, mappers=None, has_selectable=False): +if has_selectable or (self.with_polymorphic and self.with_polymorphic[1]): +return self.iterate_properties +elif mappers is None: +return self._default_polymorphic_properties else: return iter(util.unique_list( chain(*[list(mapper.iterate_properties) for mapper in [self] + mappers]) )) - + @property def properties(self): raise NotImplementedError(Public collection of MapperProperty objects is On Dec 3, 2008, at 9:22 AM, Gaetan de Menten wrote: On Wed, Dec 3, 2008 at 15:03, Michael Bayer [EMAIL PROTECTED] wrote: um yeah, actually this behavior is affecting all multi-level usage of polymorphic_union. So, while polymorphic_union is quite obviously (since nobody has noticed this pretty glaring issue) on the decline in the 0.5 series, this is quite severe and ill try to have a look at it today. Do you want a bug report for this? -- Gaëtan de Menten http://openhex.org --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups sqlalchemy group. To post to this group, send email to sqlalchemy@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en -~--~~~~--~~--~--~---
[sqlalchemy] relation join problem
Hi i tried the following example, but i cant get the join to work: CREATE TABLE product ( idINTEGER, price NUMERIC(15,2) NOT NULL, PRIMARY KEY(id) ); CREATE TABLE i18n_product ( id INTEGER, lang VARCHAR(2), descriptionVARCHAR(150) NOT NULL, PRIMARY KEY(id, lang), FOREIGN KEY(id) REFERENCES product(id) ); python: class Product(Base): __table__ = Table('product', Base.metadata, autoload=True) class I18NProduct(Base): __table__ = Table('i18n_product', Base.metadata, autoload=True) product = relation(Product, backref=backref('i18n')) x=session.query(Product).filter(Product.id==1183).join('i18n').filter (I18NProduct.lang=='en').one() the sql looks of the JOIN looks good, but if i access x.i18n, another queries is build which returns all of my language entry for one product, what i try to get is one product description in the given language. please tell me how to do that correctly, thank you :) cheers Dom --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups sqlalchemy group. To post to this group, send email to sqlalchemy@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en -~--~~~~--~~--~--~---
[sqlalchemy] Re: Polymorphic concrete inheritance question
On Wed, Dec 3, 2008 at 16:04, Michael Bayer [EMAIL PROTECTED] wrote: this ones big, i can handle it. the attached patch makes your case work, but the problem represented here still makes itself apparent in other ways and I havent strength tested this patch. you might want to see if this patch works in all of your test cases. FWIW, my (only) more complete test involving polymorphic concrete inheritance passes too (and produces correct SQL). Your patch seem fine and doesn't seem to break unrelated tests. Thanks for the quick reaction time, as usual. -- Gaëtan de Menten http://openhex.org --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups sqlalchemy group. To post to this group, send email to sqlalchemy@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en -~--~~~~--~~--~--~---
[sqlalchemy] Re: New instance ExtraStat with identity key (...) conflicts with persistent instance ExtraStat
I've met so few other Farrells, maybe we ARE related!! Get it, related, in a SqlAlchemy group. Oh man I'm such a geek!! -Original Message- From: sqlalchemy@googlegroups.com [mailto:[EMAIL PROTECTED] On Behalf Of Bob Sent: Tuesday, December 02, 2008 9:00 AM To: sqlalchemy@googlegroups.com Subject: [sqlalchemy] Re: New instance ExtraStat with identity key (...) conflicts with persistent instance ExtraStat I keep thinking one of my relatives has emailed me when you post here and I get all excited. Any chance you can change your name ? :-) 2008/12/2 Doug Farrell [EMAIL PROTECTED]: Michael, Thanks for the pointer, that makes great sense, and once again points how my generally small database design skills. I'll update my code to try this out. Again, Thanks! Doug From: sqlalchemy@googlegroups.com [mailto:[EMAIL PROTECTED] On Behalf Of Michael Bayer Sent: Saturday, November 29, 2008 9:28 PM To: sqlalchemy@googlegroups.com Subject: [sqlalchemy] Re: New instance ExtraStat with identity key (...) conflicts with persistent instance ExtraStat Simon's suggestion about the duplicate name still holds. Your relation from Stat-ExtraStat currently needs to be one-to-one since you cannot have more than one ExtraStat referencing a single Stat, due to the PK constraint on ExtraStat.name. The error is raising at the point of query() since autoflush is kicking in - use session.flush() to isolate the error. On Nov 29, 2008, at 12:18 PM, Doug Farrell wrote: Hi all, I'm having a problem with a new instance of a relation conflicting with an existing instance. I'm using SA 0.5rc with Sqlite3. Here are my simplified classes: class Stat(sqladb.Base): __tablename__ = stats name = Column(String(32), primary_key=True) total= Column(Integer) created = Column(DateTime, default=datetime.datetime.now()) updated = Column(DateTime) states = Column(PickleType, default={}) extraStats = relation(ExtraStat, backref=stat) class ExtraStat(sqladb.Base): __tablename__ = extrastats name = Column(String(32), ForeignKey(stats.name), primary_key=True) total= Column(Integer) created = Column(DateTime, default=datetime.datetime.now()) updated = Column(DateTime) states = Column(PickleType, default={}) The above Stat class has a one-to-many relationship with the ExtraStat class (which I think I've implemented correctly). Later in the program I create an in memory data model that has as part of it's components two dictionaries that contain Stat instances. Those Stat instances have relationships to ExtraStat instances. My problem comes in the following when I'm trying to update the data in those instances/tables. Here is a section of code that throws the exception: pressName = press%s % pressNum # add new ExtraStat instances as relations self._addProductStatsPress(productType, pressName) self._addPressStatsProduct(pressName, productType) try: extraStat = session.query(Stat). \ filter(Stat.name==productType). \ join(extraStats). \ filter(ExtraStat.name==pressName).one() except: extraStat = ExtraStat(pressName, ExtraStat.PRESS_TYPE) self.productStats[productType].extraStats.append(extraStat) extraStat.states.setdefault(sstate, 0) extraStat.states[sstate] += 1 extraStat.updated = now extraStat = session.merge(extraStat) try: extraStat = session.query(Stat). \ filter(Stat.name==pressName). \ join(extraStats). \ filter(ExtraStat.name==productType).one() throws exception right here except: extraStat = ExtraStat(productType, ExtraStat.PRODUCT_TYPE) self.pressStats[pressName].extraStats.append(extraStat) extraStat.states.setdefault(sstate, 0) extraStat.states[sstate] += 1 extraStat.updated = now The marked area is wear it throws the exception. I'm not sure what to do here to get past this, any help or ideas would be greatly appreciated. The exact exception is as follows: Sqlalchemy.orm.exc.FlushError: New instance [EMAIL PROTECTED] With identity key (class '__main__.ExtraStat',(u'C',)) conflicts with persistent instance [EMAIL PROTECTED] Thanks! Doug r more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en -~--~~~~--~~--~--~--- --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups sqlalchemy group. To post to this group, send email to
[sqlalchemy] removing instrumentation from a mapped object
Hi there, is there any canonical way of removing all SQAlchemy instrumentation from a mapped object? I'm trying to feed a complex mapped class instance through PyAMF (which serializes objects to be read in Adobe Flash). This works fine for scalar attributes but not for collections, e.g. a one-to-many relation collection. PyAMF getattr()s the list, which is actually not a list() but a sqlalchemy.orm.collections.InstrumentedList, and subsequently tries to encode all of its _* and __* attributes. Thanks, Simon --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups sqlalchemy group. To post to this group, send email to sqlalchemy@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en -~--~~~~--~~--~--~---
[sqlalchemy] Re: Polymorphic concrete inheritance question
it needed some more work. the final version of this fix is in r5412. On Dec 3, 2008, at 10:49 AM, Gaetan de Menten wrote: On Wed, Dec 3, 2008 at 16:04, Michael Bayer [EMAIL PROTECTED] wrote: this ones big, i can handle it. the attached patch makes your case work, but the problem represented here still makes itself apparent in other ways and I havent strength tested this patch. you might want to see if this patch works in all of your test cases. FWIW, my (only) more complete test involving polymorphic concrete inheritance passes too (and produces correct SQL). Your patch seem fine and doesn't seem to break unrelated tests. Thanks for the quick reaction time, as usual. -- Gaëtan de Menten http://openhex.org --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups sqlalchemy group. To post to this group, send email to sqlalchemy@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en -~--~~~~--~~--~--~---
[sqlalchemy] Re: removing instrumentation from a mapped object
On 3 Dez., 18:32, Michael Bayer [EMAIL PROTECTED] wrote: I would also posit that PyAMF's behavior might be inappropriate in this case. InstrumentedList is a subclass of list so I don't immediately see why it would treat it differently. Upon further inspection, this was exactly the case. Basically telling PyAMF to encode lists as list, not as generic object, solved my problem. For the record, here's how it works (using PyAMF 0.3.1): amf3.Encoder.type_map.insert(0, ((list,), writeList)) Michael, you saved my day. Thank you :-) --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups sqlalchemy group. To post to this group, send email to sqlalchemy@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en -~--~~~~--~~--~--~---
[sqlalchemy] SQLAlchemy Sphinx Documentation Preview
We've created a new branch and are in the process of migrating all of our documentation over to Sphinx. The process has gone well and we have a working demo of the full system online. By converting to Sphinx, we get the huge advantage of being on a standardized platform that everyone can understand and contribute towards. All kinds of wacky old code, some of it four or more years old, has been removed (and we thank it for its service). The docs are now split into Main Documentation and API Reference. Because Sphinx allows very flexible layout of docstring-generated documentation, Main Documentation is shrinking and the docstrings used by API Reference, which is an all new section that replaces the old straight down modules display, are growing dramatically, which means more documentation is centralized across the site/pydocs and there's less redundancy. What we are now looking for with regards to the demo is: - comments/suggestions regarding layout, styling. Some layout changes were forced by Sphinx, and others (most) are improvements that Sphinx allowed us to achieve. I'm not a CSS guru or a designer so suggested patches to the CSS and templates would be welcome. If Todd Grimason is out there, feel free to chime in :) . - proofreaders. The content on the demo is maybe 60% of the way there and we're combing through finding issues related to the Sphinx conversion, as well as things that have just been wrong all along. We would love to get patches against the doc build correcting as many issues as possible. - authors. No excuses now , we're on the most standard platform there is for docs. If you have better verbiage for sections or docstrings which aren't clear, are nonexistent (like many of the dialects) or are out of date (theres lots), we want to see suggestions. More elaborate suggestions regarding new sections and organization are welcome too as the structure is completely open ended. - people who understand LaTex to work on the PDF side of things. This one's totally over my head as far as how to get a pdf file out of this thing (pdflatex is fairly inscrutable on a mac). Sphinx 0.6 is required, which at the time of this writing is not yet released so you'll have to check out Sphinx from its mercurial repository if you want to do builds. View the content online at: http://www.sqlalchemy.org/docs/sphinxtest/ Checkout the SVN branch and do a build: http://svn.sqlalchemy.org/sqlalchemy/branches/sphinx --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups sqlalchemy group. To post to this group, send email to sqlalchemy@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en -~--~~~~--~~--~--~---
[sqlalchemy] Re: relation join problem
That would be desc = session.query(I18Product).filter_by(id=1183, lang=en).one() The Problem with your query is that you query() for Product, not for I18NProduct, so regardless of and filter and join functions you specify, you will always receice Product objects. Think of query (Product) as a final filter which creates Product objects from the returned rows, and ignores everything which is not a column of Product. For x.i18n (a property of Product) to work as you described, have a look at http://www.sqlalchemy.org/docs/04/mappers.html#advdatamapping_relation_collections . You'd basically want to setup your relation() as a dict using the lang column as key. Simon On 3 Dez., 16:33, Dom [EMAIL PROTECTED] wrote: Hi i tried the following example, but i cant get the join to work: CREATE TABLE product ( id INTEGER, price NUMERIC(15,2) NOT NULL, PRIMARY KEY(id) ); CREATE TABLE i18n_product ( id INTEGER, lang VARCHAR(2), description VARCHAR(150) NOT NULL, PRIMARY KEY(id, lang), FOREIGN KEY(id) REFERENCES product(id) ); python: class Product(Base): __table__ = Table('product', Base.metadata, autoload=True) class I18NProduct(Base): __table__ = Table('i18n_product', Base.metadata, autoload=True) product = relation(Product, backref=backref('i18n')) x=session.query(Product).filter(Product.id==1183).join('i18n').filter (I18NProduct.lang=='en').one() the sql looks of the JOIN looks good, but if i access x.i18n, another queries is build which returns all of my language entry for one product, what i try to get is one product description in the given language. please tell me how to do that correctly, thank you :) cheers Dom --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups sqlalchemy group. To post to this group, send email to sqlalchemy@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en -~--~~~~--~~--~--~---
[sqlalchemy] Abstract base class
Hello, is there a way with the ORM layer to have abstract base class like in django ? http://docs.djangoproject.com/en/dev/topics/db/models/#abstract-base- classes Another somehow related question is there any plan for declarative base to support inheritance ala django ? Regards, Guillaume --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups sqlalchemy group. To post to this group, send email to sqlalchemy@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en -~--~~~~--~~--~--~---
[sqlalchemy] Re: inferring object class/table directly
On Wed, 3 Dec 2008 08:58:42 -0500 (EST), [EMAIL PROTECTED] [EMAIL PROTECTED] wrote: On Tue, 2 Dec 2008 at 23:21, Faheem Mitha wrote: Yes, I was looking for this, and printed out obj.__dict__ but didn't see it there. A dictionary of attributes is very useful in theory, but doesn't always seem to have all attributes. Is this documented anywhere? Try dir(obj). You'll see it there. The __dict__ is only for instance attributes. Excellent. This is the first I've heard of this function, but apparently it is a Python builtin. Well past time to go read the docs for this, I guess. Not too difficult. You can also use type(obj) instead of obj.__class__. I thought of trying this, but didn't. It didn't seem likely to work, anyway. Is either of these preferred over the other in terms of API stability, and if so, why? obj.__class__ is a python thing, as is type(obj), and neither of those is changing in python 3.0, so I'd think both would be stable API wise :) However, the documentation of __class__ makes it clear you get the class back, while the documentation of the 'type' built in function does not...so I'd lean toward using __class__, myself. It also means you'll get an earlier error if you accidentally pass something that is not actually a class instance into your function. Thanks. That's very helpful. Regards, Faheem. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups sqlalchemy group. To post to this group, send email to sqlalchemy@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en -~--~~~~--~~--~--~---
[sqlalchemy] Re: Abstract base class
On Dec 3, 2008, at 1:26 PM, Guillaume wrote: Hello, is there a way with the ORM layer to have abstract base class like in django ? http://docs.djangoproject.com/en/dev/topics/db/models/#abstract-base- classes sure, just pass along cls=MyBaseClass along to declarative_base(). You can also make your own metaclass if you wanted, and pass it in as metaclass=MyMetaClass, or you can use the individual components within declarative_base explicitly if you wanted to roll it yourself. This is all in the docstrings for declarative. Another somehow related question is there any plan for declarative base to support inheritance ala django ? declarative supports all three of SQLA's table inheritance forms fully.It pretty much happens automatically when you make a subclass, and you just need to pass along polymorphic_on/ polymorphic_identity into __mapper_args__. If Django supported some kind of inheritance scenario that we don't I'd be very interested to see that :) . --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups sqlalchemy group. To post to this group, send email to sqlalchemy@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en -~--~~~~--~~--~--~---
[sqlalchemy] Re: Polymorphic concrete inheritance question
this is still there: File sqlalchemy/orm/mapper.py, line 168, in __init__ self.with_polymorphic[1] = self.with_polymorphic[1].alias() TypeError: 'tuple' object does not support item assignment also, related question: once there is A-B-C, concrete, how u'd get some A by id? query(A).filter_by(id=1) returns 3 objects, one of A,B,C. i guess some filter( mapper.polymorphic_on == 'Aidentity') should be there, but how to guess if A is inherited concrete hence needs that? or is that automaticaly done by query.get() and i missed it? On Wednesday 03 December 2008 19:29:31 Michael Bayer wrote: it needed some more work. the final version of this fix is in r5412. On Dec 3, 2008, at 10:49 AM, Gaetan de Menten wrote: On Wed, Dec 3, 2008 at 16:04, Michael Bayer [EMAIL PROTECTED] wrote: this ones big, i can handle it. the attached patch makes your case work, but the problem represented here still makes itself apparent in other ways and I havent strength tested this patch. you might want to see if this patch works in all of your test cases. FWIW, my (only) more complete test involving polymorphic concrete inheritance passes too (and produces correct SQL). Your patch seem fine and doesn't seem to break unrelated tests. Thanks for the quick reaction time, as usual. -- Gaëtan de Menten http://openhex.org --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups sqlalchemy group. To post to this group, send email to sqlalchemy@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en -~--~~~~--~~--~--~---
[sqlalchemy] Re: Polymorphic concrete inheritance question
and maybe related: def query_by_id( klas, idname, oid, .): q = session.query( klas).filter_by( **{idname: oid}) # filter by atype for concrete m = class_mapper( klas) concrete = bool( m.with_polymorphic[1] ) if concrete: q= q.filter( m.polymorphic_on == klas.__name__) return q.all() generates a query like SELECT pu_a.* FROM (SELECT A.* FROM A UNION ALL SELECT C.* FROM C) AS pu_a, (SELECT A.* FROM A UNION ALL SELECT C.* FROM C) AS pu_a WHERE pu_a.db_id = ? AND pu_a.atype = ? with repeated union twice in the FROM, and error thereof. Somehow the mapper.polymorphic_on is not recognized as already being there and pulls the union once more? if there's no q.filter( m.polymorphic_on == klas.__name__), no errors (but returns multiple objects). this on latest trunk. svil On Wednesday 03 December 2008 19:29:31 Michael Bayer wrote: it needed some more work. the final version of this fix is in r5412. On Dec 3, 2008, at 10:49 AM, Gaetan de Menten wrote: On Wed, Dec 3, 2008 at 16:04, Michael Bayer [EMAIL PROTECTED] wrote: this ones big, i can handle it. the attached patch makes your case work, but the problem represented here still makes itself apparent in other ways and I havent strength tested this patch. you might want to see if this patch works in all of your test cases. FWIW, my (only) more complete test involving polymorphic concrete inheritance passes too (and produces correct SQL). Your patch seem fine and doesn't seem to break unrelated tests. Thanks for the quick reaction time, as usual. -- Gaëtan de Menten http://openhex.org --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups sqlalchemy group. To post to this group, send email to sqlalchemy@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en -~--~~~~--~~--~--~---
[sqlalchemy] Re: Polymorphic concrete inheritance question
thats strange, i dont suppose you could send me how you're setting up that polymorphic union On Dec 3, 2008, at 3:05 PM, [EMAIL PROTECTED] wrote: and maybe related: def query_by_id( klas, idname, oid, .): q = session.query( klas).filter_by( **{idname: oid}) # filter by atype for concrete m = class_mapper( klas) concrete = bool( m.with_polymorphic[1] ) if concrete: q= q.filter( m.polymorphic_on == klas.__name__) return q.all() generates a query like SELECT pu_a.* FROM (SELECT A.* FROM A UNION ALL SELECT C.* FROM C) AS pu_a, (SELECT A.* FROM A UNION ALL SELECT C.* FROM C) AS pu_a WHERE pu_a.db_id = ? AND pu_a.atype = ? with repeated union twice in the FROM, and error thereof. Somehow the mapper.polymorphic_on is not recognized as already being there and pulls the union once more? if there's no q.filter( m.polymorphic_on == klas.__name__), no errors (but returns multiple objects). this on latest trunk. svil On Wednesday 03 December 2008 19:29:31 Michael Bayer wrote: it needed some more work. the final version of this fix is in r5412. On Dec 3, 2008, at 10:49 AM, Gaetan de Menten wrote: On Wed, Dec 3, 2008 at 16:04, Michael Bayer [EMAIL PROTECTED] wrote: this ones big, i can handle it. the attached patch makes your case work, but the problem represented here still makes itself apparent in other ways and I havent strength tested this patch. you might want to see if this patch works in all of your test cases. FWIW, my (only) more complete test involving polymorphic concrete inheritance passes too (and produces correct SQL). Your patch seem fine and doesn't seem to break unrelated tests. Thanks for the quick reaction time, as usual. -- Gaëtan de Menten http://openhex.org --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups sqlalchemy group. To post to this group, send email to sqlalchemy@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en -~--~~~~--~~--~--~---
[sqlalchemy] Re: Polymorphic concrete inheritance question
can i... maybe something like table_A = Table( 'A', meta, Column( 'name', String(length=200, ), ), Column( 'db_id', primary_key= True, type_= Integer, ), ) table_B = Table( 'B', meta, Column( 'dataB', String(length=200 ), Column( 'db_id', primary_key= True, type_= Integer, ), ) table_C = Table( 'C', meta, Column( 'name', String(length=200 ), Column( 'dataC', String(length=200 ), Column( 'db_id', primary_key= True, type_= Integer, ), ) meta.create_all() class A( Base): props = ['db_id', 'name'] class B( Base): props = ['db_id', 'dataB'] class C( A): props = ['db_id', 'name', 'dataC'] pu_a = polymorphic_union( { 'A': table_A, 'C': table_C, }, 'atype', 'pu_a', ) #concrete table mapper_A = mapper( A, table_A, polymorphic_identity= 'A', polymorphic_on= pu_a.c.atype, with_polymorphic= ('*', pu_a.alias( 'pu_a' )), ) mapper_B = mapper( B, table_B, with_polymorphic= None, ) mapper_C = mapper( C, table_C, concrete= True, inherits= mapper_A, polymorphic_identity= 'C', with_polymorphic= None, ) #populate a = A() b = B() c = C() a.name = 'anna' b.dataB = 'gun' c.name = 'cc' c.dataC = 'mc' session = create_session() session.save(a) session.save(b) session.save(c) session.flush() def query_by_id( session, klas, idname, oid, ): #single if config.session_clear: session.clear() q = session.query( klas).filter_by( **{idname: oid}) #TODO: filter by atype for concrete? m = class_mapper( klas) concrete = bool( m.with_polymorphic[1] ) print print m.polymorphic_on print m.with_polymorphic[1].c.atype if concrete: q= q.filter( m.polymorphic_on == klas.__name__) #if concrete: q= q.filter( m.with_polymorphic[1].c.atype == klas.__name__) return q.all() print query_by_id( session, A, 'db_id', 1, str(a) ) filtering by m.with_polymorphic[1].c.atype is ok (commented). i guess i see the error: polymorphic_on is on pu_a, with_polymorphic is on pu_a.alias()... but u have some autoaliasing in there anyway, no? btw, have u planned to get relations to polymorphic concretes to work somewhen ? eventualy query.get(id) to work? i.e. identity to include the type On Wednesday 03 December 2008 22:21:12 Michael Bayer wrote: thats strange, i dont suppose you could send me how you're setting up that polymorphic union On Dec 3, 2008, at 3:05 PM, [EMAIL PROTECTED] wrote: and maybe related: def query_by_id( klas, idname, oid, .): q = session.query( klas).filter_by( **{idname: oid}) # filter by atype for concrete m = class_mapper( klas) concrete = bool( m.with_polymorphic[1] ) if concrete: q= q.filter( m.polymorphic_on == klas.__name__) return q.all() generates a query like SELECT pu_a.* FROM (SELECT A.* FROM A UNION ALL SELECT C.* FROM C) AS pu_a, (SELECT A.* FROM A UNION ALL SELECT C.* FROM C) AS pu_a WHERE pu_a.db_id = ? AND pu_a.atype = ? with repeated union twice in the FROM, and error thereof. Somehow the mapper.polymorphic_on is not recognized as already being there and pulls the union once more? if there's no q.filter( m.polymorphic_on == klas.__name__), no errors (but returns multiple objects). this on latest trunk. svil On Wednesday 03 December 2008 19:29:31 Michael Bayer wrote: it needed some more work. the final version of this fix is in r5412. On Dec 3, 2008, at 10:49 AM, Gaetan de Menten wrote: On Wed, Dec 3, 2008 at 16:04, Michael Bayer [EMAIL PROTECTED] wrote: this ones big, i can handle it. the attached patch makes your case work, but the problem represented here still makes itself apparent in other ways and I havent strength tested this patch. you might want to see if this patch works in all of your test cases. FWIW, my (only) more complete test involving polymorphic concrete inheritance passes too (and produces correct SQL). Your patch seem fine and doesn't seem to break unrelated tests. Thanks for the quick reaction time, as usual. -- Gaëtan de Menten http://openhex.org --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups sqlalchemy group. To post to this group, send email to
[sqlalchemy] Re: Polymorphic concrete inheritance question
this is still there: File sqlalchemy/orm/mapper.py, line 168, in __init__ self.with_polymorphic[1] = self.with_polymorphic[1].alias() TypeError: 'tuple' object does not support item assignment try mapping to something that is already an alias() (this would lend insight into your other problem) ah, okay, i'm aliasing my stuff, but removed the alias to check something else and stepped on this one. passing in a list works too. also, related question: once there is A-B-C, concrete, how u'd get some A by id? query(A).filter_by(id=1) returns 3 objects, one of A,B,C. i guess some filter( mapper.polymorphic_on == 'Aidentity') should be there, but how to guess if A is inherited concrete hence needs that? or is that automaticaly done by query.get() and i missed it? if B and C inherit from A, then three objects is the right answer in that case. put this in the bucket of reasons why concrete table inheritance in conjunction with polymorphic loading by default should be avoided. I was about to advise using query.with_polymorphic() only, no mapper polymorphic at all, for this case but I realized this is currently incompatible with the need for a polymorphic discriminator column. so maybe we can add that as a third argument to with_polymorphic(). okay, then i get this as answer to my other question - so concrete polymorhism relations/get()/identity on top of it are blue_sky. that's okay - just put a line about it in the docs. dbcook is throwing warnings about it since long time. svil --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups sqlalchemy group. To post to this group, send email to sqlalchemy@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en -~--~~~~--~~--~--~---
[sqlalchemy] I can replace an object with another in python, by changing the object dict to the other object dict. How does it settle with sqlalchemy? Does it works when another mapped object poin
I wrote it on usage reciepts, but no one answered yet. The reason I'm doing so, is to solve the following problem: I have an object that is compounded from the fields - obj_id, num1, num2, num3. obj_id is my primary key. I want to create a save method for the object's class, that will do the following: If the object is in the session, save it. Else, if there is another object in the db with the same num1 and num2, use the object in the db instead of the current one, and warn the user if num3 is different. So it's quite like merge, but not necessarily on the primary key. Now, I want that use the object in the db wouldn't be by returning the object after the merge (original object if didn't exist, and db_object if existed), but really replacing it (self.dict = existing_object.dict), so one can use that object afterwards, without being confused. I know that I can make a constraint in the DB that num1 and num2 would be unique so that object won't be created (the user will get an exception), but it won't really be a fix for my problem, because it's important for my users not to get that kind of exceptions (Especially because I have another mapped clazz, that is the contatiner of many obj, so way they will save that class they don't won't to deal with the case that one of the obj already existed). --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups sqlalchemy group. To post to this group, send email to sqlalchemy@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en -~--~~~~--~~--~--~---
[sqlalchemy] Re: replace an object.dict with another
so u'd get two objects sharing same dict, and changin one will break the other, in a hideous way. better copy stuff one by one, or invent some other way. On Wednesday 03 December 2008 22:47:34 [EMAIL PROTECTED] wrote: I wrote it on usage reciepts, but no one answered yet. The reason I'm doing so, is to solve the following problem: I have an object that is compounded from the fields - obj_id, num1, num2, num3. obj_id is my primary key. I want to create a save method for the object's class, that will do the following: If the object is in the session, save it. Else, if there is another object in the db with the same num1 and num2, use the object in the db instead of the current one, and warn the user if num3 is different. So it's quite like merge, but not necessarily on the primary key. Now, I want that use the object in the db wouldn't be by returning the object after the merge (original object if didn't exist, and db_object if existed), but really replacing it (self.dict = existing_object.dict), so one can use that object afterwards, without being confused. I know that I can make a constraint in the DB that num1 and num2 would be unique so that object won't be created (the user will get an exception), but it won't really be a fix for my problem, because it's important for my users not to get that kind of exceptions (Especially because I have another mapped clazz, that is the contatiner of many obj, so way they will save that class they don't won't to deal with the case that one of the obj already existed). --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups sqlalchemy group. To post to this group, send email to sqlalchemy@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en -~--~~~~--~~--~--~---
[sqlalchemy] Re: I can replace an object with another in python, by changing the object dict to the other object dict. How does it settle with sqlalchemy? Does it works when another mapped object
SQLAlchemy instruments classes using an event-based system that intercepts all setattribute and collection mutation operations, and logs these events as things to be reconciled when the Session is flushed. Additionally, the __dict__ of the object itself is referenced by the InstanceState object which is SQLAlchemy's per- object manager. Thirdly, the InstanceState object itself is placed inside of the __dict__ of every object instance, and this cannot be shared among multiple objects. So for these three reasons and probably more, using the old Python trick of replacing __dict__ will lead to poor results. To populate the state of an object with that of another, use a setattr() based approach: for k in dir(object1): setattr(object2, k, getattr(object1, k)) On Dec 3, 2008, at 3:47 PM, [EMAIL PROTECTED] wrote: The reason I'm doing so, is to solve the following problem: I have an object that is compounded from the fields - obj_id, num1, num2, num3. obj_id is my primary key. I want to create a save method for the object's class, that will do the following: If the object is in the session, save it. Else, if there is another object in the db with the same num1 and num2, use the object in the db instead of the current one, and warn the user if num3 is different. So it's quite like merge, but not necessarily on the primary key. Now, I want that use the object in the db wouldn't be by returning the object after the merge (original object if didn't exist, and db_object if existed), but really replacing it (self.dict = existing_object.dict), so one can use that object afterwards, without being confused. the most straightforward way to accomplish this would be a custom __new__ method, so that when you say: x = MyObject(num1=x, num2=y) the __new__() would do the session work to find the old object and return that instead, if present. There is a usage recipe on the Wiki that does something like this, except its 0.4 specific, and uses a metaclass in combination with a homegrown cache - I wrote it years ago and it can be done much more simply. Just use __new__(). --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups sqlalchemy group. To post to this group, send email to sqlalchemy@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en -~--~~~~--~~--~--~---
[sqlalchemy] Re: Polymorphic concrete inheritance question
On Dec 3, 2008, at 3:45 PM, [EMAIL PROTECTED] wrote: okay, then i get this as answer to my other question - so concrete polymorhism relations/get()/identity on top of it are blue_sky. that's okay - just put a line about it in the docs. dbcook is throwing warnings about it since long time. modify your code to use the query.with_polymorphic('*', selectable, some_discriminator_column) approach in r5413, and then tell me what issues remain. its not appropriate for with_polymorphic to be set on a concrete mapper() in most cases. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups sqlalchemy group. To post to this group, send email to sqlalchemy@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en -~--~~~~--~~--~--~---
[sqlalchemy] Re: Polymorphic concrete inheritance question
On Wednesday 03 December 2008 23:28:01 Michael Bayer wrote: On Dec 3, 2008, at 3:45 PM, [EMAIL PROTECTED] wrote: okay, then i get this as answer to my other question - so concrete polymorhism relations/get()/identity on top of it are blue_sky. that's okay - just put a line about it in the docs. dbcook is throwing warnings about it since long time. modify your code to use the query.with_polymorphic('*', selectable, some_discriminator_column) approach in r5413, and then tell me what issues remain. u mean a plain mapper without polymorphism, then above query().with_poly? that seem to work. but it still needs .filter( discriminator==identity) for a get()-like op to work. and in this case each query() will also needs the .with_poly(..) stuff, so whole automatics (specifying things once) gets lost. ah, forget it. i dont need concrete without working relations, just played with the tests. if u decide one day to finish this concrete stuff and need coverage of fullblown combinations of A-B-C + all-possible-references, yell. it's in dbcook/tests/test_ABC_inh_ref_all.py the loss of synchron between the polymorphic_on and the with_polymorphic[1] if alias'ed, may be a problem one day for someone, but it's up to you. ciao svil --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups sqlalchemy group. To post to this group, send email to sqlalchemy@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en -~--~~~~--~~--~--~---
[sqlalchemy] Re: Polymorphic concrete inheritance question
On Dec 3, 2008, at 5:15 PM, [EMAIL PROTECTED] wrote: On Wednesday 03 December 2008 23:28:01 Michael Bayer wrote: On Dec 3, 2008, at 3:45 PM, [EMAIL PROTECTED] wrote: okay, then i get this as answer to my other question - so concrete polymorhism relations/get()/identity on top of it are blue_sky. that's okay - just put a line about it in the docs. dbcook is throwing warnings about it since long time. modify your code to use the query.with_polymorphic('*', selectable, some_discriminator_column) approach in r5413, and then tell me what issues remain. u mean a plain mapper without polymorphism, then above query().with_poly? that seem to work. but it still needs .filter( discriminator==identity) for a get()-like op to work. no, you say session.query(cls).get(x) - you're looking for class cls. get() is not going to figure that out for you. I think concrete inheritance is more useful when its less magical. and in this case each query() will also needs the .with_poly(..) stuff, so whole automatics (specifying things once) gets lost. if you want polymorphic loading. Which you usually shouldn't, if you are using concrete inheritance. it is not optimized for that. ah, forget it. i dont need concrete without working relations, just played with the tests. there we go ! --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups sqlalchemy group. To post to this group, send email to sqlalchemy@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en -~--~~~~--~~--~--~---
[sqlalchemy] Re: I can replace an object with another in python, by changing the object dict to the other object dict. How does it settle with sqlalchemy? Does it works when another mapped object
A. Thanks for this great idea. From your suggestion, I realize that if I am going to use the new method, than I must enforce my __new__ (and __init__) to get all the unique fields as arguments. Then, if the object already exists in the db to return it, and otherwise save the new object. An important part of it is save the new object, because if I won't save the object, and one would do something like: obj1 = MyObject(num1 = x, num2 = y) obj1.save() obj2 = MyObject(num1 = x, num2 = x) obj2.num2 = y obj2.save() Then obj2 would not really be merged with obj1, and I will get a constraint exception - the thing my customers afraid of the most. So far, so good. But my customers are really weird, and two weeks ago they asked me to totally change the design of my project, so they will be able to use my mapped objects, without saving them to the db. Meaning, they wants to be able to do the following thing: 1. Create many MyObject instances. 2. Do some operations on them. (The features that my program supply) 3. Save some of them to the db, if they are interesting, but most of them, just throw away, without even saving them in the first place. The reason they asked it, is because in some of the cases, they will want to only use the classes in the API that I provide, for stuff that aren't important enough to be saved in the db, and without suffering from the overhead of saving objects to the db. So the case that I mentioned above with changing the attribute num2 can happen. Another option, is not to allow them to change num2, unless the object is saved already in the db. (using property) It would be weird. B. So I can settle with a merge() method that returns an object. I think it's the only solution (beside forcing them to work with saving to the db). Actually, it's not too bad. But it's also not easy, I tell you, to write such a function. Because what happens if one of the things that defines me, a part of my uniqueness, is not really a unique field, but a list of objects that are connected to me in a many- to-many relationship from another table. And what if I need to call merge() on each one of them. And what if two of them are evaluated to be the same object, so I need to fix the list. oof! On 3 דצמבר, 23:25, Michael Bayer [EMAIL PROTECTED] wrote: SQLAlchemy instruments classes using an event-based system that intercepts all setattribute and collection mutation operations, and logs these events as things to be reconciled when the Session is flushed. Additionally, the __dict__ of the object itself is referenced by the InstanceState object which is SQLAlchemy's per- object manager. Thirdly, the InstanceState object itself is placed inside of the __dict__ of every object instance, and this cannot be shared among multiple objects. So for these three reasons and probably more, using the old Python trick of replacing __dict__ will lead to poor results. To populate the state of an object with that of another, use a setattr() based approach: for k in dir(object1): setattr(object2, k, getattr(object1, k)) On Dec 3, 2008, at 3:47 PM, [EMAIL PROTECTED] wrote: The reason I'm doing so, is to solve the following problem: I have an object that is compounded from the fields - obj_id, num1, num2, num3. obj_id is my primary key. I want to create a save method for the object's class, that will do the following: If the object is in the session, save it. Else, if there is another object in the db with the same num1 and num2, use the object in the db instead of the current one, and warn the user if num3 is different. So it's quite like merge, but not necessarily on the primary key. Now, I want that use the object in the db wouldn't be by returning the object after the merge (original object if didn't exist, and db_object if existed), but really replacing it (self.dict = existing_object.dict), so one can use that object afterwards, without being confused. the most straightforward way to accomplish this would be a custom __new__ method, so that when you say: x = MyObject(num1=x, num2=y) the __new__() would do the session work to find the old object and return that instead, if present. There is a usage recipe on the Wiki that does something like this, except its 0.4 specific, and uses a metaclass in combination with a homegrown cache - I wrote it years ago and it can be done much more simply. Just use __new__(). --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups sqlalchemy group. To post to this group, send email to sqlalchemy@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en -~--~~~~--~~--~--~---
[sqlalchemy] Re: I can replace an object with another in python, by changing the object dict to the other object dict. How does it settle with sqlalchemy? Does it works when another mapped object
On Dec 3, 2008, at 6:39 PM, [EMAIL PROTECTED] wrote: B. So I can settle with a merge() method that returns an object. I think it's the only solution (beside forcing them to work with saving to the db). Actually, it's not too bad. But it's also not easy, I tell you, to write such a function. Because what happens if one of the things that defines me, a part of my uniqueness, is not really a unique field, but a list of objects that are connected to me in a many- to-many relationship from another table. And what if I need to call merge() on each one of them. And what if two of them are evaluated to be the same object, so I need to fix the list. oof! merge() doesn't do much that you couldn't do manually on your own. if you need to write a jacked up merge()-like function that compares collections and things, i dont think Python will let you down in that regard. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups sqlalchemy group. To post to this group, send email to sqlalchemy@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en -~--~~~~--~~--~--~---