On Feb 24, 2014, at 2:41 PM, Luke <lmerg...@gmail.com> wrote:

> Hi,
> 
> 
> 
> class Response(Writing):
>     # All responses are associated with Writing. Writing/Articles may have
>     # several responses
>     # 
>     __tablename__ = 'response'
>     id = Column('id', ForeignKey('writing.id'), primary_key=True)
>     respondee_id = Column('respondee', ForeignKey('article.id'), 
> nullable=False)
>  
>     # So, No, I don't know what I'm doing here...
>     respondee = relationship(
>         'Response', backref='respondant',
>         primaryjoin=('Writing.respondant' == 'Response.respondee'))
>     __mapper_args__ ={
>         'polymorphic_identity': 'response', }

1. for the syntax on primaryjoin as a string, it has to be all one string:

primaryjoin = “Writing.id == Response.respondee_id”

see the examples at:

http://docs.sqlalchemy.org/en/rel_0_9/orm/relationships.html#relationship-primaryjoin
http://docs.sqlalchemy.org/en/rel_0_9/orm/extensions/declarative.html#configuring-relationships

2. The primaryjoin is between columns, which are accessed using the attribute 
name given, such as Writing.id.  not the name of a relationship (respondent).

3. the relationship joins two tables between primary key columns and foreign 
key columns.  In this case, you’re saying you’d like “response.respondee” to 
refer to “article.id”, so you’d be setting up primary join in that way…..but

4. ..the mapping doesn’t seem to make sense in that regard, you have Response 
linked to Response, and not Article.   If Article is just one kind of Writing, 
and Response belongs to any kind of Writing, it would be:

class Response(Writing):
    __tablename__ = 'response'
    id = Column('id', ForeignKey('writing.id'), primary_key=True)
    respondee_id = Column(ForeignKey('writing.id'), nullable=False)

    writing = relationship(Writing,
                    remote_side=Writing.id,
                    backref="responses",
                    primaryjoin=Writing.id == respondee_id)

    __mapper_args__ = {'polymorphic_identity': 'response',
                        'inherit_condition': id == Writing.id}

inherit condition is needed as “response” now has two ways to link directly to 
“writing”.

5. On the topic of “not an expert in SQL”, I will say that this kind of design 
where “everything inherits from joined-table X” is extremely common for people 
I see moving from a pure OO background to beginning to mix SQL into their 
modeling.   It’s not “wrong” per se and can be a useful design, but in my 
experience is overused, and it also leads to queries that are very complicated 
on the render side and often not very performant.   You should consider very 
carefully how many columns will actually be on “Writing” as well as how many 
kinds of “sub-tables” will really be needed to import these columns on 
“writing”; additionally, you should consider how much of a need you will have 
to query across all kinds of “Writing” objects at the same time.  In practice, 
this use case is rare; your app will either need to see lists of Articles, or 
it will need to see the list of Responses given a parent Writing.   If Writing 
has only a handful of columns, it would be much more efficient and simple from 
both a storage and a querying perspective to just have a “response” table, an 
“article” table, and then a few columns on both that just happen to be the 
same.  From the object modeling side, you can keep Response and Article as 
subclasses of Writing, however you can have Writing itself be a non-mapped 
mixin or __abstract__ class.  The mapping becomes extremely simple and from a 
SQL perspective much more succinct and performant:

class Writing(Base):
    __abstract__ = True
    id = Column(Integer, primary_key=True)  # gets copied out to subclasses

class Article(Writing):
    __tablename__ = 'article'

class Response(Writing):
    __tablename__ = 'response'
    respondee_id = Column(ForeignKey('article.id'), nullable=False)
    writing = relationship(Article, backref="responses")


Attachment: signature.asc
Description: Message signed with OpenPGP using GPGMail

Reply via email to