Cool, I think the approach you outlined briefly works, and I look forward 
to hopefully seeing it in the next release. 

For now, I will just add the columns back to the AutocreatedGroup class. 

Again, thank you. I really appreciate your help. I'll make sure to make my 
emails in the future more explanatory according to your input.

On Wednesday, August 15, 2012 12:22:59 PM UTC-4, Michael Bayer wrote:
>
>
> On Aug 15, 2012, at 11:41 AM, Kuba Dolecki wrote:
>
> You responded! Woot. Thanks. Here's some additional info:
>
> 1. __tablename__ is generated automatically based on the class name. 
> Flask-SQLAlchemy does this for us. The __tablename__ for AutocreatedGroup 
> and TopicAutocreatedGroup model is both "autocreated_group".
>
>
> <many questions here, removed once I read point #2>
>
>
> 2. Sorry, I might have included too much code in my snippet. Group extends 
> Community through joined table inheritance (primary key with foreign key to 
> community). AutocreatedGroup extends Group in the same manner. The 
> relationship of interest is between AutocreatedGroup and 
> TopicAutocreatedGroup. TopicAutocreatedGroup does appear to inherit through 
> a single table. 
>
>
> OH.   no, this wasn't *enough* code.  I always need to know the full 
> expanse of classes and tables in play.  I'll recreate the full mapping now 
> based on your descriptions here in order to reproduce.
>
>
> 3. Yeah, I'm redefining polymorphic_on for Group since it depends on a 
> boolean switch. I'm doing the same for AutocreatedGroup since it depends on 
> the name of the class. 
>
> AutocreatedGroup and TopicAutocreatedGroup do appear to have all of the 
> same columns of Group and Community. The AutocreatedGroup table does have 
> the topic_created_from_id column, but that same column doesn't appear in 
> the mapper. 
>
>
> there is logic added to declarative that detects columns applied to a 
> single table inheritance subclass, and moves them up to the superclass 
> table, mapping it only for the subclass.  Due to the complex and deep chain 
> of mappings here, this logic is likely failing.  let's create a test case 
> and see.  (goes to do that).....OK yeah this isn't going to work right now 
> and would require a major architectural change to the expression system in 
> order to accommodate.   The declarative system adds the new column to the 
> AutocreatedGroup.__table__ correctly.  However, AutocreatedGroup's "mapped" 
> table is the join() of community->group->autocreated_group.  The collection 
> of columns on this join() object is determined only once from the Table 
> objects given to it.   Adding a new column to one of those Table objects 
> after the fact is not affecting that collection so the column isn't mapped.
>
> There's ways this might work but they are definitely destabilizing, I'l 
> try to see if I can put something into 0.8 for that - basically I'd make 
> derived selectables add an event listener to the selectable they're derived 
> from, so that new column additions can propagate.
>
> However, to make this work for now you'd need to declare 
> topic_created_from_id on the AutocreatedGroup class directly.   A more 
> involved workaround would be to delay the production of mappings on the 
> hierarchy, though in 0.7 you need to do a slightly hacky approach for that 
> (it's what's described in 
> https://bitbucket.org/sqlalchemy/sqlalchemy/src/f47a971874b6/examples/declarative_reflection/declarative_reflection.py
> ).
>
>
>
> Thanks, again. I'm definitely not a SQL Alchemy expert, so your help is 
> appreciated greatly. 
>
> On Wednesday, August 15, 2012 11:21:41 AM UTC-4, Michael Bayer wrote:
>>
>>
>> On Aug 15, 2012, at 10:45 AM, Kuba Dolecki wrote:
>>
>> Hi,
>>
>> We've used joined table inheritance up to this point, but performance 
>> issues are making us explore single table inheritance. I'm running into a 
>> problem with mapper configuration. Using SQLAlchemy 0.7.8, Flask-SQLAlchemy 
>> 0.16, and Flask 0.8. Here is the inheritance: 
>>
>>
>> there are many things that are confusing about this model.
>>
>> 1.  I don't see any mention of __tablename__ anywhere.  Where is the 
>> table defined ?
>>
>> 2. You say this is single table inheritance, but I see each subclass has 
>> it's own primary key column, with a foreign key column pointing back to the 
>> superclass "table" (which isn't present).   This doesn't fit with single 
>> table inheritance at all.
>>
>> 3. There's a second re-definition of "polymorphic_on".   This isn't 
>> necessarily a mistake, as it is supported that loading a specific 
>> sub-hierarchy may have a different system of determining polymorphic 
>> identity - usually this applies to concrete schemes.  But with joined or 
>> single table inheritance it's extremely unusual, as the base table is what 
>> determines object identity in both of these cases.   If you load a 
>> collection of "community" rows, the ORM needs to decide from that base 
>> table alone what the subclass should be.   It won't see a 
>> sub-polymorphic-on unless the original query was against that subclass.
>>
>>
>> class Community(BaseModel, db.Model):
>>    # Bar
>>
>> class Group(Community):
>>     ###
>>         Group utilized joined table inheritance to extend Community
>>     ###
>>     id  = db.Column(db.Integer, db.ForeignKey('community.id'), 
>> primary_key=True, nullable=False)
>>     autocreated = db.Column(db.Boolean, nullable=False, default=False)
>>
>>     @declared_attr
>>         def __mapper_args__(cls):
>>             name = cls._name()
>>             identity = {
>>                 'polymorphic_on': case([
>>                     (cls.autocreated == True, "autocreated_group"),
>>                     (cls.autocreated == False, "group")
>>                 ]),
>>                 'polymorphic_identity': name
>>             }
>>             return identity
>>
>> class AutocreatedGroup(Group):
>>     ###
>>         AutocreatedGroup extends Group through joined table inheritance
>>     ###
>>     id = db.Column(db.Integer, db.ForeignKey('group.id'), 
>> primary_key=True, \
>>         nullable=False)
>>     
>>     @declared_attr
>>     def __mapper_args__(cls):
>>         name = cls._name()
>>         identity = {
>>             'polymorphic_on': cls.autocreated_type,
>>             'polymorphic_identity': name
>>         }
>>         return identity
>>
>> class TopicAutocreatedGroup(AutocreatedGroup):
>>     ###
>>         TopicAutocreatedGroup extends AutocreatedGroup through single 
>> table inheritance
>>     ###
>>     @declared_attr
>>     def __mapper_args__(cls):
>>         return {'polymorphic_identity': cls._name()}
>>
>>     topic_created_from_id = db.Column(
>>         db.Integer,
>>         db.ForeignKey('topic.id'),
>>         nullable = True
>>     )
>>     topic_created_from = db.relation(
>>         "Topic",
>>         primaryjoin="Topic.id == 
>> TopicAutocreatedGroup.topic_created_from_id",
>>         backref=db.backref("topic_groups", uselist=True),
>>         uselist=False, lazy='subquery'
>>     )
>>
>> Here is the stacktrace: 
>> Traceback (most recent call last):
>>   File "/srv/.env/lib/python2.6/site-packages/flask/app.py", line 1518, 
>> in __call__
>>     return self.wsgi_app(environ, start_response)
>>   File "/srv/.env/lib/python2.6/site-packages/flask/app.py", line 1506, 
>> in wsgi_app
>>     response = self.make_response(self.handle_exception(e))
>>   File "/srv/.env/lib/python2.6/site-packages/flask/app.py", line 1504, 
>> in wsgi_app
>>     response = self.full_dispatch_request()
>>   File "/srv/.env/lib/python2.6/site-packages/flask/app.py", line 1264, 
>> in full_dispatch_request
>>     rv = self.handle_user_exception(e)
>>   File "/srv/.env/lib/python2.6/site-packages/flask/app.py", line 1260, 
>> in full_dispatch_request
>>     rv = self.preprocess_request()
>>   File "/srv/.env/lib/python2.6/site-packages/flask/app.py", line 1387, 
>> in preprocess_request
>>     rv = func()
>>   File "/srv/franklin-api/api/helpers/login_manager.py", line 53, in 
>> _load_user
>>     user = User.for_auth_token(token)
>>   File "/srv/franklin-api/api/models/user.py", line 584, in for_auth_token
>>     user_for_token = cls.query.filter(cls.auth_token == 
>> auth_token).first()
>>   File "/srv/.env/lib/python2.6/site-packages/flask_sqlalchemy.py", line 
>> 394, in __get__
>>     mapper = orm.class_mapper(type)
>>   File "/srv/.env/lib/python2.6/site-packages/sqlalchemy/orm/util.py", 
>> line 660, in class_mapper
>>     mapperlib.configure_mappers()
>>   File "/srv/.env/lib/python2.6/site-packages/sqlalchemy/orm/mapper.py", 
>> line 2255, in configure_mappers
>>     raise e
>> InvalidRequestError: One or more mappers failed to initialize - can't 
>> proceed with initialization of other mappers.  Original exception was: 
>> Class <class 'api.models.autocreated_group.TopicAutocreatedGroup'> does not 
>> have a mapped column named 'topic_created_from_id'
>>
>>
>> It appears the Columns inside classes that inherit through single table 
>> inheritance are not included in the mapper. Any idea of what may be going 
>> wrong?
>>
>> Thank you,
>> Kuba
>>
>> P.S. What should __mapper_args__ look like for AutocreatedGroup? Should 
>> "topic_created_from_id" be automatically included in the 
>> "excluded_properties" value? Currently, it's empty if I print it out. 
>>
>> -- 
>> You received this message because you are subscribed to the Google Groups 
>> "sqlalchemy" group.
>> To view this discussion on the web visit 
>> https://groups.google.com/d/msg/sqlalchemy/-/l3a-3tBjaf4J.
>> To post to this group, send email to sqlal...@googlegroups.com.
>> To unsubscribe from this group, send email to 
>> sqlalchemy+...@googlegroups.com.
>> For 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 view this discussion on the web visit 
> https://groups.google.com/d/msg/sqlalchemy/-/iUiRCq6w7bcJ.
> To post to this group, send email to sqlal...@googlegroups.com<javascript:>
> .
> To unsubscribe from this group, send email to 
> sqlalchemy+...@googlegroups.com <javascript:>.
> For 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 view this discussion on the web visit 
https://groups.google.com/d/msg/sqlalchemy/-/ReJ_h3Y3RYAJ.
To post to this group, send email to sqlalchemy@googlegroups.com.
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en.

Reply via email to