Thanks for persisting with me - your solution was almost perfect, and
really pointing me in the right direction. Below is what eventually
worked:
areas = relationship('DbArea', backref = backref('routes',
order_by = 'DbRoute.name'),
secondary = area_relationship_table,
primaryjoin = area_id == area_relationship_table.c.descendent,
secondaryjoin = DbArea.area_id ==
area_relationship_table.c.ancestor,
innerjoin = True, order_by = DbArea.name,
foreign_keys = [area_relationship_table.c.ancestor,
area_relationship_table.c.descendent])
I swapped your descendent and ancestor, and added the foreign_keys due
a warning that I was receiving 'SAWarning: No ForeignKey objects were
present in secondary table 'area_relationship' ...'. I also added
some sorting for convenience.
This back and forth really helped me out in my work, but also to
better understand SA and particularly SA relationships. A million
thanks!
Jon
On Jan 9, 11:22 pm, Michael Bayer <[email protected]> wrote:
> On Jan 9, 2012, at 11:58 PM, jonstjohn wrote:
>
> > The route and area relationship is similar to the hypothetical problem
> > of a business location. Suppose you have a set of business locations,
> > each in a specific city. The business must be associated with one and
> > only one city. The city is located in ever widening areas, e.g., the
> > county, region, state, country, planet, etc. Suppose you want to find
> > all businesses within a given county, or a state. I'm not sure I
> > agree that storing the city id in the business violates normalization,
> > since the business can have only one city.
> > And I'm not sure that
> > storing the business id in every geographical designation (i.e.,
> > country, region, state, etc) is a better design. On the contrary, I
> > think that you would want to store the city id with the business, and
> > the relationship between geographical entities separately.
>
> I was going to suggest relating the DbRoute directly to DbArea, then I
> noticed that you've actually done this with DbRoute.area_id and DbRoute.area,
> hadn't noticed that before.
>
> DbRoute.areas asks relationship() to do something impossible - you're asking
> it to load DbArea objects but then the relationship is forced to not look at
> any columns that are actually in the DbArea table. You have it linking
> back to DbRoute.area_id on both sides. Hence it tries to link
> DbRoute.area_id to DbArea and fails.
>
>
>
> > As I mentioned in the original post, I can construct an SQL query that
> > gets at this relationship (sorry if it got buried):
>
> > SELECT route.route_id, route.name
> > FROM area
> > INNER JOIN area_relationship ON area.area_id =
> > area_relationship.ancestor
> > INNER JOIN route ON route.area_id = area_relationship.descendent
> > WHERE area.area_id = 1
>
> This query suggests linking route on one side and area on the other, which is
> more traditional, so you'd just need to link to DbArea.area_id:
>
> areas = relationship('DbArea', backref = 'routes',
> secondary = area_relationship_table,
> primaryjoin = area_id == area_relationship_table.c.ancestor,
> secondaryjoin = DbArea.area_id == area_relationship_table.c.descendent,
> innerjoin=True)
>
> This should produce the equivalent idea, an implicit join when lazily loaded
> and INNER JOIN if joinedload() is used.
--
You received this message because you are subscribed to the Google Groups
"sqlalchemy" group.
To post to this group, send email to [email protected].
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.