Question

So I've spent some time on this and keep running around in circles and getting nowhere so I figured I'd come to the experts!

Using Flask 0.9 and SQLAlchemy 0.7.9 I'm attempting to create a Gallery page which has a collection of Gallery's. Each gallery has a collection of sub galleries and each sub gallery has a collection of photo's. My first attempt shown below clearly does not work:

class Gallery(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(64))
    subgals = db.relationship('SubGallery', backref='author', lazy='dynamic')

    def __repr__(self):
        return '<Gallery - %r>' % (self.title)


class SubGallery(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(64))
    photos = db.relationship('Photo', backref='author', lazy='dynamic')
    gallery_id = db.Column(db.Integer, db.ForeignKey('gallery.id'))

    def __repr__(self):
        return '<Gallery - %r>' % (self.title)


class Photo(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(64))
    href = db.Column(db.String(128))
    subgallery_id = db.Column(db.Integer, db.ForeignKey('subgallery.id'))

    def __repr__(self):
        return '<Photo - %r>' % (self.title)

and returns this error:

sqlalchemy.exc.ArgumentError: Could not determine join condition between parent/child tables on relationship SubGallery.photos.  Specify a 'primaryjoin' expression.  If 'secondary' is present, 'secondaryjoin' is needed as well.

I've been researching alternate relationship configurations but am not 100% sure what I need. My gut tells me I need an Adjacency Relationship but I haven't been able to get very far with it. I attempted a many to many mapping but I haven't seen much material how to map 3 classes together.

I REALLY appreciate any input and insight you all have to offer with this and thanks!!

Was it helpful?

Solution

I think you database is setup correctly, you have two one-to-many relationships and that seems fine.

The "could not determine..." error from SQLAlchemy is just saying that there is not enough information in your model for SQLAlchemy to figure out what the join condition is for the relationship between the sub-gallery and the photo tables.

SQLAlchemy tries to guess a lot of things from how you name things, it expects consistency. I believe in this case it is not finding what it needs due to your usage of camel case SubGallery.

You could, as the error message suggests, add an explicity primaryjoin argument to the relationship and then SQLAlchemy will be happy, or else you can change your names to help SQLAlchemy figure it out by itself.

I have modified your definitions by renaming SubGallery to 'Subgallery` and that seems to work. Below is the modified models:

class Gallery(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(64))
    subgals = db.relationship('Subgallery', backref='author', lazy='dynamic')

    def __repr__(self):
        return '<Gallery - %r>' % (self.title)


class Subgallery(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(64))
    photos = db.relationship('Photo', backref='author', lazy='dynamic')
    gallery_id = db.Column(db.Integer, db.ForeignKey('gallery.id'))

    def __repr__(self):
        return '<Gallery - %r>' % (self.title)


class Photo(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(64))
    href = db.Column(db.String(128))
    subgallery_id = db.Column(db.Integer, db.ForeignKey('subgallery.id'))

    def __repr__(self):
        return '<Photo - %r>' % (self.title)

And I've used this little quick and dirty test script to make sure the relationships were working:

db.create_all()
g = Gallery(title = "a")
db.session.add(g)
db.session.commit()
sg = Subgallery(title = "a1", author = g)
db.session.add(sg)
db.session.commit()
p = Photo(title = "a1p", href="href", author = sg)
db.session.add(p)
db.session.commit()
for subgal in g.subgals.all():
    print subgal
    print subgal.author
    for photo in subgal.photos.all():
        print photo
        print photo.author
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top