1

I am working on a project using Flask and SQLAlchemy. I've succesfully created my database and populated it with data. Now I'm working on the API endpoints, using Blueprints. However, I want to use raw SQL queries here instead of ORM provided by SQLAlchemy (this is a requirement for the project). However, when I retrieve the engine from my db object, and run the query, it's accessing the wrong database and as a result returning the wrong data. The database it's accessing is actually the default postgres database, with a single relation titled users with a single user called postgres.

However, when I just run the query using the ORM, it accesses the correct database and executes the correct query. I've researched this for a while now, and haven't come up with any answers. Here is the directory structure of my project

.
├── api
│   ├── __init__.py
│   ├── models.py
│   └── views
│       ├── auth.py
│       └── users.py
├── db_create.py
├── db_drop.py
├── manager.py
├── populate.py
├── README.md

Here is the not working users.py file:

import json
from api import app, db
from api.models import User
from flask import Blueprint, request
from flask import jsonify
import api

mod = Blueprint('users', __name__)

engine = db.engine
conn = engine.connect()

@mod.route('/users')
def get_all_users():
    result = conn.execute("SELECT * FROM user")
    users  = []
    for row in result:
        user = {}
        for key in row.keys():
            user[key] = row[key]
        users.append(user)
    return jsonify({'users' : users})

And here is the working users.py:

import json
from api import app, db
from api.models import User
from flask import Blueprint, request
from flask import jsonify
import api

mod = Blueprint('users', __name__)

engine = db.engine
conn = engine.connect()

@mod.route('/users')
def get_all_users():
    users = db.session.query(User).all()
    users_arr = []
    for user in users:
        user_dict = {}
        user_dict["email"] = user.email
        user_dict["username"] = user.username
        user_dict["password"] = user.password
        user_dict["name"] = user.name
        user_dict["latitude"] = user.latitude
        user_dict["longitude"] = user.longitude
        users_arr.append(user_dict)
    return jsonify({'users' : users_arr})

I have my DB models defined in models.py, and I use this (very crude) way of instantiating the database in db_create.py:

from api import db

db.create_all()
db.session.commit()

Here is my init.py in api directory:

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_cors import CORS
from flask_login import LoginManager, login_required
import os

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = "postgresql://postgres:postgres@localhost/mydbname"

db = SQLAlchemy(app)

from api import models

# import and register blueprints
from api.views import users
app.register_blueprint(users.mod)

Even when I try to access the user relation from psql, it doesn't work. It returns a 1-tuple with postgres as the user. However, accessing other relations from psql works fine (and I think this suggests they work fine for raw SQL in SQLAlchemy).

Pastebin of the psql CLI: https://pastebin.com/raw/gPyr4Hbk

However, if I check the DB through something like DataGrip, it reports the user relation correctly and shows the data correctly.

Screenshot of DataGrip

  • In this case nice code example to learn from. – ZF007 Mar 20 '18 at 23:23
  • @sytech I already had read through that before posting this. My issue isn't that it's failing to execute the query, but instead that it's executing the query on a completely different database. When I hit the endpoint, this is the json I get back: { "users": [ { "user": "postgres" } ] } – Abdullahi Abdalla Mar 20 '18 at 23:31
  • So you're using multiple databases? Please update your question with your settings and db file where you create the `db` object. Also note the solution uses `db.engine.execute` not `db.engine.connect().execute` which is what you have, though I don't think that's directly related to your problem. – sytech Mar 20 '18 at 23:34
  • @sytech edited my ppost. I am not using multiple databases, I'm just letting SQLAlchemy connect to the database and then create the relations. EDIT: disregard. What I recently typed about not being able to see it in psql. – Abdullahi Abdalla Mar 20 '18 at 23:50
  • @sytech, Just found out the error. [User is a reserved keyword in Postgres, and to actually access my user relation I need to wrap it in quotations.](https://stackoverflow.com/questions/21051521/postgres-drop-table-syntax-error) – Abdullahi Abdalla Mar 21 '18 at 00:23

1 Answers1

1

Postgres drop table syntax error

User is a keyword in Postgres. To access the relation correctly, wrap it quotes.