Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sqlalchemy one to many relationship join?

I am trying to do a simple join query like this,

SELECT food._id, food.food_name, food_categories.food_categories FROM food JOIN food_categories ON food.food_category_id = food_categories._id

but keep receiving an error. Here is how my classes are setup.

class Food_Categories(db.Model):
    __tablename__ = 'food_categories'
    _id = db.Column(db.Integer, primary_key=True)
    food_categories = db.Column(db.String(30))

class Food(db.Model):
    __tablename__ = 'food'
    _id = db.Column(db.Integer, primary_key=True)
    food_name = db.Column(db.String(40))
    food_category_id = db.Column(db.Integer, ForeignKey(Food_Categories._id))
    food_category = relationship("Food_Categories")

My query function looks like this.

@app.route('/foodlist')
def foodlist():
    if request.method == 'GET':
        results = Food.query.join(Food_Categories.food_categories).all()

    json_results = []
    for result in results:
        d = {'_id': result._id,
         'food': result.food_name,
         'food_category': result.food_categories}
    json_results.append(d)

    return jsonify(user=json_results)

I am using Flask. When I call the route I get this error.

AttributeError: 'ColumnProperty' object has no attribute 'mapper'

I essentially want this:

|      id       |    food_name    |    food_category    |

and have the food_category_id column replaced with the actual name of the food category located in other table.

Are my tables/relationships set up correctly? Is my query setup correctly?

like image 867
user3502585 Avatar asked Apr 12 '14 03:04

user3502585


1 Answers

Your tables and relationships are setup correctly. Your query needs a change.

The reason for an error is the fact that you try to perform a join on the column (Food_Categories.food_categories) instead of a Table (or mapped model object). Technically, you should replace your query with the one below to fix the error:

results = Food.query.join(Food_Categories).all()

This will fix the error, but will not generate the SQL statement you desire, because it will return instances of Food only as a result even though there is a join.

In order to build a query which will generate exactly the SQL statement you have in mind:

results = (db.session.query(Food._id, Food.food_name,
        Food_Categories.food_categories,)
    .join(Food_Categories)).all()
for x in results:
    # print(x)
    print(x._id, x.food_name, x.food_categories)

Please note that in this case the results are not instances of Food, but rather tuples with 3 column values.

like image 129
van Avatar answered Sep 18 '22 08:09

van