You may wish to review the "Collection Configuration" section of the documentation. There are a few main, built-in ways to deal with how relationships are handled in SQLAlchemy, and that section of the documentation shows the various ways.
By default, when you have...
class Companies(db.Model):
...
branches = db.relationship("Branches")
...
Loading a Company will load all of the branches in (and by default, it loads them into a list). Therefore, after retrieving a company, company.branches
returns to you a list of branches. Because it is a list, it doesn't have functions such as filter()
or all()
. If you are not expecting a large list of branches, this might be preferred since it might make more sense for you to use branches as a list rather than as a query object. Having this as a list allows you to do things such as...
company = session.query(Companies).first()
my_branch = Branches(...)
company.branches.append(my_branch)
session.commit()
This will properly create the new Branches
object without needing to add it specifically to the session (which I think is pretty nifty).
As a side note, if you were to do type(company.branches)
, you would not get <type 'list'>
, because in order to pull off this magic, SQLAlchemy will actually set branches
to an object type that works LIKE a list, but actually has additional SQLAlchemy-specific info. This object type, if you haven't guessed, is the "InstrumentedList" that you are getting the error message about.
However, you might not want to do this; specifically, this requires you to load in all of the branches at once, and you might only want to load a few in at a time because you have thousands of them (thousands of branches in a company, just imagine the bureaucracy...)
So, you change the relation, as the docs say...
A key feature to enable management of a large collection is the so-called “dynamic” relationship. This is an optional form of relationship() which returns a Query object in place of a collection when accessed. filter() criterion may be applied as well as limits and offsets, either explicitly or via array slices:
It appears that this is what you want to do if you want to be able to do things like company.branches.filter(...).all()
. To do this, you would do as the docs show, by making the lazy
attribute of the relationship "dynamic"...
class Companies(db.Model):
...
branches = db.relationship("Branches", lazy='dynamic')
...
It looks like you've done this already for the branches -> sales relationship, but you haven't for the company -> branches relationship, which is what is giving you the error.