0

I am learning to build an API using Python, Flask and SQLAlchemy. When I started integrating SQLAlchemy into my code, any request that was trying to use SQLAchemy would just do nothing. No Error codes, it just sits there and spins. Here is the main portion of my code:

App.py

from flask import Flask
from flask_restful import Api
from flask_jwt import JWT

from security import authenticate, identity
from Resources.user import UserRegister
from Resources.item import Item, ItemList


app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = "postgresql://postgres:mypassword@localhost:5000/mydatabase"
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.config['PROPAGATE_EXCEPTIONS'] = True
app.secret_key = 'jose'
api = Api(app)


jwt = JWT(app, authenticate, identity)

api.add_resource(Item, '/item/<string:name>')
api.add_resource(ItemList, '/items')
api.add_resource(UserRegister, '/register')

if __name__ == '__main__':
    from db import db
    db.init_app(app)
    app.run(port = 5000, debug = True)

db.py

from flask_sqlalchemy import SQLAlchemy 

db = SQLAlchemy()

item.py-Models

from db import db

class ItemModel(db.Model):
    __tablename__ = 'parts'

    partid  = db.Column(db.Integer, primary_key = True)
    partdescript = db.Column(db.String(80))
    lastcost = db.Column(db.Float(precision=2))


    def __init__(self, partid, partdescript, _price):
        self.partid = partid
        self.partdescript = partdescript
        self.price = price


    def json(self):
        return {'name': self.partid, 'partdescript': self.partdescript, 'price':self.price}

    @classmethod
    def find_by_name(cls, partid):
        print("find_by_name")
        #print(partid)
        #print(cls.query.filter_by(partid = partid))

        qry = cls.query.filter_by(partid = partid).first()  # this is where it is getting stuck

        return qry

    def save_to_db(self):

        db.session.add(self)
        db.session.commit()


    def delete_from_db(self):
        db.session.delete(self)
        db.session.commit()

item.py-Resources

from flask_restful import Resource, reqparse
from flask_jwt import jwt_required
from Models.item import ItemModel

class Item(Resource):
    parser = reqparse.RequestParser()

    parser.add_argument(
        'partdescript',
        type = str,
        required = False,
        help = "This field cannot be left blank!"
    )

    parser.add_argument(
        'lastcost',
        type = float,
        required = True,
        help = "This field cannot be left blank!"
    )

    #@jwt_required()
    def get(self, name):
        #print("get")
        part = ItemModel.find_by_name(name)
        #print(part)

        if part:
            #print("get if statement")
            return part.json(), 201
        return {'message': 'Part not found'}, 404

    @jwt_required()
    def post(self, name): #need to have the parser.add_argument for each field
        if ItemModel.find_by_name(name):
            return {'message': "An item with name '{}' already exists.".format(name)}, 400

        data = Item.parser.parse_args()

        item = ItemModel(name, data['partdescript'], data['lastcost'])

        try:
            item.save_to_db()
        except:
            return {"message": "An error occurred inserting the item."}, 500

        return item.json(), 201

    @jwt_required()
    def delete(self, name):
        item = ItemModel.find_by_name(name)
        if item:
            item.delete_from_db()

        return {'message': 'Item deleted'}

    @jwt_required()
    def put(self, name):
        data = Item.parser.parse_args()

        item = ItemModel.find_by_name(name)
        updated_item = ItemModel(name, "",data['lastcost']) #might need to put item descript in

        if item is None:
            item = ItemModel(name, data['lastcost'])
        else:
            item.lastcost = data['lastcost']

        item.save_to_db()

        return item.json()


class ItemList(Resource):
    @jwt_required()
    def get(self):
        return {'items': [item.json() for item in ItemModel.query.all()]}

If I just use python to access my database correctly the requests function just fine. It is only when I am trying to use SQLAlchemy. Someone that I have been getting help from thought that it might be because I had both SQLAlchemy and direct access in my code. I converted everything to SQLAlchemy and now all of the requests just sit and spin. My old code that does not use SQLAlchemy still works.

Things I have tried: Rebooting system Uninstall and reinstall SQLAlchemy sending requests using cURL instead of Postman putting wrong database name in connection to see if I would get an error. running all applications as administrator

I put in several print statements to find where it is failing. If I remove a .first() or .all() then my code continues to run and I can print what the query is supposed to be but that also makes it so the query is not sent at all.

Any ideas why SQLAchemy would just sit and Spin?

1 Answers1

4

Im not sure if this is the code as is, but your database connection URI seems to be pointing back to your flask app.

app.config['SQLALCHEMY_DATABASE_URI']="postgresql://postgres:mypassword@localhost:5000/mydatabase"

5000 is the default port for flask apps.

5432 is the default port for postgres.

My first suggestion would be to make sure the connection URI you're giving SQLAlchemy is correct.

SQLAlchemy doesn't attempt to connect to the database when the flask app starts; it will only attempt to connect to the database when the first query is executed.

You might be experiencing a deadlock, where your app is trying to connect to the database on port 5000, but port 5000 (your flask app) is not responding because its currently busy trying to get a connection to the database.

See this answer which points out that only a single request can be served at a time using the flask development server with default options.