Cannot POST a JSON object to Database using Flask Python - python

I'm trying to post and get objects using Flask but I keep getting sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) no such table: object.
I tried doing POST into http://127.0.0.1/data
and the json I provided is
{
"oid": "123456789",
"size": "1234"
}
Below is my code
from flask import Flask, request
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///db.sqlite3'
db = SQLAlchemy(app)
class Object(db.Model):
oid = db.Column(db.Integer, primary_key=True)
size = db.Column(db.Integer)
def __repr__(self):
return f'Object: {self.oid}, Size: {self.size}'
#app.route('/')
def index():
return 'DSAP_2022'
#app.route('/data/<oid>', methods=['GET'])
def getObject(oid):
obj = Object.query.filter_by(oid=oid).first()
if obj is None:
return 'Object not found', 404
return repr(obj)
#app.route('/data', methods=['POST'])
def putObject():
obj = Object(oid=request.json['oid'], size=request.json['size'])
db.session.add(obj)
db.session.commit()
return 'OK'
if __name__ == '__main__':
app.run()
I am using Postman to submit my requests. and the index() works, however, both getObject and putObject doest not work because of the same error.

You're never calling db.create_all() to create the database tables. You would need something like:
from flask import Flask, request
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///db.sqlite3'
db = SQLAlchemy(app)
class Object(db.Model):
oid = db.Column(db.Integer, primary_key=True)
size = db.Column(db.Integer)
def __repr__(self):
return f'Object: {self.oid}, Size: {self.size}'
# Create tables corresponding to sqlalchemy models
db.create_all()
#app.route('/')
def index():
return 'DSAP_2022'
#app.route('/data/<oid>', methods=['GET'])
def getObject(oid):
obj = Object.query.filter_by(oid=oid).first()
if obj is None:
return 'Object not found', 404
return repr(obj)
#app.route('/data', methods=['POST'])
def putObject():
obj = Object(oid=request.json['oid'], size=request.json['size'])
db.session.add(obj)
db.session.commit()
return 'OK'
if __name__ == '__main__':
app.run()

Related

SQLAlchemy not creating tables with db.create_all()

This question has been asked a few times I never been able to fix my problem since a few days. I tried to create a new object in my sqllite db related to a Model that I created but I always have this issue:
Arguments: (OperationalError('(sqlite3.OperationalError) no such table: sku_model'),)
app.py
import requests
from flask import Flask
from flask_crontab import Crontab
from app.routes import routes_blueprint
from app.config import BaseConfig, BasicConfig, TestConfig
import os
from statistics import median
import click
from app.models import SKUModel, db
def create_app():
app = Flask(__name__)
app.config["SECRET_KEY"] = "any secret key"
app.config["SQLALCHEMY_DATABASE_URI"] = BaseConfig.SQLALCHEMY_DATABASE_URI
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
db.init_app(app)
app.register_blueprint(routes_blueprint)
crontab.init_app(app)
return app
def setup_database(app):
with app.app_context():
db.create_all()
app.logger.info("DB init!")
crontab = Crontab()
if __name__ == "__main__":
app = create_app()
# not os.path.isfile(BaseConfig.SQLALCHEMY_DATABASE_URI):
setup_database(app)
app.run()
database.py
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
models.py
import flask_sqlalchemy
db = flask_sqlalchemy.SQLAlchemy()
class SKUModel(db.Model):
id = db.Column(db.Integer, primary_key=True)
sku = db.Column(db.String)
product_title = db.Column(db.String)
quantity = db.Column(db.Integer)
price = db.Column(db.Float)
# JSON serializer
def to_json(self):
return {
"id": self.id,
"sku": self.sku,
"product_title": self.product_title,
"quantity": self.quantity,
"price": self.price,
}
config.py
import os
# default config
class BaseConfig(object):
DEBUG = False
# shortened for readability
SECRET_KEY = '\xbf\xb0\x11\xb1\xcd\xf9\xba\x8bp\x0c...'
SQLALCHEMY_PATH = "/tmp/database.db"
#SQLALCHEMY_DATABASE_URI = "sqlite:////tmp/sku.db"
SQLALCHEMY_DATABASE_URI = "sqlite:///" + SQLALCHEMY_PATH
class TestConfig(BaseConfig):
DEBUG = True
TESTING = True
WTF_CSRF_ENABLED = False
SQLALCHEMY_DATABASE_URI = 'sqlite:///:memory:'
class BasicConfig(BaseConfig):
DATASET_PATH = "app/data/dataset.json"
routes.py
from itertools import product
import json
from statistics import median
import requests
from flask import Blueprint, request
from app.models import SKUModel, db
from app.core import get, get_all, update_dataset, get_5_highest, update_21, create, delete, get_lowest
routes_blueprint = Blueprint("route_blueprint", __name__)
#routes_blueprint.route("/")
def hello():
return "Hello World!"
# Retrieve the current timezone using the WorldTimeAPI (http://worldtimeapi.org) for any country available in the service
#routes_blueprint.route("/timezone/<string:area>/<string:region>")
def timezone(area, region):
url = f"http://worldtimeapi.org/api/timezone/{area}/{region}"
response = requests.get(url)
return (
{"UTF:": response.json()["utc_offset"]}
if response.ok
else {"response error": response.text, "http code": response.status_code}
)
# Get one SKU
#routes_blueprint.route("/sku/<int:id>")
def get_sku(id):
sku = get(id)
return sku.to_json() if sku else ("Not found", 404)
# Get all SKUs
#routes_blueprint.route("/sku")
def get_all_sku():
return json.dumps([sku.to_json() for sku in get_all()])
#routes_blueprint.route("/sku/update", methods=["GET"])
def update_from_dataset():
return update_dataset()
# Get the 5 best prices for a SKU
#routes_blueprint.route("/sku/best", methods=["GET"])
def get_best_sku():
return json.dumps([sku.to_json() for sku in get_5_highest()])
# Update a SKU from an ID by increasing it's price by 21%
#routes_blueprint.route("/sku/<int:id>", methods=["PUT"])
def update_sku(id):
return update_21(id).to_json()
# Create SKU from form data
#routes_blueprint.route("/sku", methods=["POST"])
def create_sku():
sku = SKUModel(
sku=request.form["sku"],
product_title=request.form["product_title"],
quantity=request.form["quantity"],
price=request.form["price"],
)
return create(sku).to_json()
# Delete SKU from ID
#routes_blueprint.route("/sku/<int:id>", methods=["DELETE"])
def delete_sku(id):
return delete(id)
# Return the lowest price for a SKU
#routes_blueprint.route("/sku/lowest")
def get_lowest_sku():
return get_lowest().to_json()
# return median price of all SKU.
#routes_blueprint.route("/sku/median")
def get_median_sku():
return {"median": median([sku.price for sku in get_all()])}
core.py
from asyncio.log import logger
from app.models import SKUModel, db
from app.config import BasicConfig
import json
import logging
LOGGER = logging.getLogger(__name__)
def get(id):
try:
return db.session.query(SKUModel).get(id)
except Exception as e:
LOGGER.error("Error while getting SKU", e)
return None
return None
def get_all():
try:
return db.session.query(SKUModel).all()
except Exception as e:
LOGGER.error("Error while getting all SKU", e)
return None
I'm sure I missed something. I heard that db.create_all() should be use after importing my model and this is what I'm doing.
When you called db.create_all() inside app.py was imported from app.database. but the db inside of app.models is defined locally. Therefore there are no models in the db inside app.py and that is why it didn't create any tables. the simplest fix would be to update app.py and change:
from app.database import db
to
from app.models import db
running this extracted code works for me. If it doesn't for you then perhaps you have an issue writing to the /tmp/database.db file.
import flask_sqlalchemy
from flask import Flask
db = flask_sqlalchemy.SQLAlchemy()
class SKUModel(db.Model):
id = db.Column(db.Integer, primary_key=True)
sku = db.Column(db.String)
product_title = db.Column(db.String)
quantity = db.Column(db.Integer)
price = db.Column(db.Float)
SQLALCHEMY_PATH = "/tmp/database.db"
SQLALCHEMY_DATABASE_URI = "sqlite:///" + SQLALCHEMY_PATH
app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] = SQLALCHEMY_DATABASE_URI
db.init_app(app)
with app.app_context():
print(db)
db.create_all()
If this simple code works, then you have to look at your code to find out why it isn't running in the expected fashion.
from models import * #Import the SQLALCHEMY object from your
#models.py i.e. db = SQLAlchemy()
db.init_app(app)
#app.before_first_request
def create_database_tables():
with app.app_context():
db.create_all()

No such table error in Flask Python while attempting PUT method

Below is an example of what I'm trying to achieve but I keep getting an error. sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) no such table: object
basically i'm trying to PUT a data that has oid, and size. and then being able to GET it.
from flask import Flask, request
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///db.sqlite'
db = SQLAlchemy(app)
class Object(db.Model):
oid = db.Column(db.Integer, primary_key=True)
size = db.Column(db.Integer)
def __repr__(self):
return '<Object %r, Size: %r>' % self.oid % self.size
#app.route('/')
def index():
return 'DSAP_2022'
#app.route('/data/<repository>/<oid>', methods=['GET'])
def getObject(repository, oid):
obj = Object.query.filter_by(oid=oid).first()
if obj is None:
return 'Object not found', 404
return 'Object %r, Size: %r' % obj.oid % obj.size
#app.route('/data/<repository>', methods=['PUT'])
def putObject():
obj = Object(oid=request.json['oid'], size=request.json['size'])
db.session.add(obj)
db.session.commit()
return 'OK'
if __name__ == '__main__':
app.run(debug=True)
what am I doing wrong here?

Can One flask have two multiple database like in the given below code?

When i try run the app the first db works proprtly but the second one does not and return error 405 could anyone post solution for multiple databes
enter image description here
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///storage.db'
db = SQLAlchemy(app)
dbTodo = SQLAlchemy(app)
class Todo(dbTodo.Model): #<=LIKE THIS
id = dbTodo.Column(db.Integer,primary_key=True)
content = dbTodo.Column(db.String(200),nullable=False)
blockId = dbTodo.Column(db.Integer)
class Blocks(db.Model): #<=LIKE THIS
id = db.Column(db.Integer,primary_key=True);
date_create = db.Column(db.DateTime,default=datetime.utcnow)
#app.route('/addto/<int:id>',methods=['POST'])
def addto(id):
if request.method == 'POST':
todo = Todo(content=request.form['content'],blockId=id)
dbTodo.session.add(todo)
dbTodo.session.commit()
print(Blocks.query.order_by(Blocks.date_create).all())
return redirect('/')
else:
print(Blocks.query.order_by(Blocks.date_create).all())
return "failed"
if __name__ == "__main__":
app.run(debug=True)
what you are looking for are binds. Have a look in the docs:
https://flask-sqlalchemy.palletsprojects.com/en/2.x/binds/
SQLALCHEMY_DATABASE_URI = 'postgres://localhost/main'
SQLALCHEMY_BINDS = {
'users': 'mysqldb://localhost/users',
'appmeta': 'sqlite:////path/to/appmeta.db'
}
db.create_all()
db.create_all(bind=['users'])
db.create_all(bind='appmeta')
db.drop_all(bind=None)

FLASK RESTful API using GET to get a specific id and returning 201 using Python

I'm trying to get a todo_ID using GET method. I'm still new at using sqlalchemy and most of the things i have tried are telling me that sqlalchemy doesn't use them. Also, can someone tell me how to use HEAD, i want my methods to return http statuses, i kinda tried using them and imported the render template but when i try to use them it says it has no idea what they are.
this is my attempt at looking at a tutorial and making changes
from flask import Flask, jsonify,json, request, render_template, abort
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config.from_pyfile('Config.py')
db = SQLAlchemy(app)
class JsonModel(object): # Class for making objects JSON serializable
def as_dict(self):
return {c.name: getattr(self, c.name) for c in self.__table__.columns}
class User(db.Model, JsonModel): # Class which is a model for the User table in the database
User_ID = db.Column(db.Integer, primary_key = True)
FirstName = db.Column(db.String(20))
LastName = db.Column(db.String(20))
def __init__(self,User_ID,FirstName, LastName):
self.User_ID = User_ID
self.FirstName = FirstName
self.LastName = LastName
class Todo(db.Model, JsonModel): # Class which is a model for the Todo table in the database
todo_ID = db.Column(db.Integer, primary_key = True)
UserID = db.Column(db.Integer, db.ForeignKey("user.User_ID"))
details = db.Column(db.String(30))
def __init__(self, UserID, details):
self.UserID = UserID
self.details = details
#app.route('/todo', methods = ['GET']) # Uses GET method to return all information in the database.
def index():
return json.dumps([u.as_dict() for u in User.query.all()+Todo.query.all()]), 201
#app.route('/todo/<int:todo_ID>', methods = ['GET'])
def get(todo_ID):
query = Todo.query.get()
return {'todo': [dict(zip(tuple(query.keys()), i)) for i in query.cursor if i[1] == todo_ID]}
#app.before_first_request #Creates everything before the first request.
def startup():
db.create_all()
if __name__ == '__main__':
app.run()
My most recent attempt was:
#app.route('/todo/<int:todo_ID>', methods = ['GET'])
def get(todo_ID):
query = Todo.query("select * from Todo")
return {'todo': [dict(zip(tuple(query.keys()), i)) for i in query.cursor if i[1] == todo_ID]}
And the error that I get is this.
query = Todo.query("select * from Todo")
TypeError: 'BaseQuery' object is not callable
127.0.0.1 - - [30/Nov/2016 21:15:28] "GET /todo/1 HTTP/1.1" 500 -
If you want to query Todo by primary key and only return one record you can use:
from flask import jsonify
#app.route('/todo/<int:todo_ID>', methods = ['GET'])
def get(todo_ID):
response = {}
todo = Todo.query.get(todo_ID)
response['id'] = todo.id
response['user_id'] = todo.UserID
response['details'] = todo.details
response['status_code'] = 201
return jsonify(response)
Or you can use Marshmallow to have a serializer for each of your models so it can serialize them for you automatically.
Not sure I understand your problem, if your intention is to return json output as response and you want to control the status code, you could
use jsonify
from flask import jsonify
#app.route('/todo/<int:todo_ID>', methods = ['GET'])
def get(todo_ID):
query = Todo.query("select * from Todo")
response = {'todo': [dict(zip(tuple(query.keys()), i)) for i in query.cursor if i[1] == todo_ID]}
response = jsonify(response)
response.status_code = 201
return response

OperationalError: (sqlite3.OperationalError) no such table: user

I'm completely new to flask and web development in general. And what I need is to login to a website using steam id. I'm doing it as it said here, but get the following error:
OperationalError: (sqlite3.OperationalError) no such table: user
It seems to open up steam website correctly but it breaks when I press Log In. So, what's my mistake ? Any help is appreciated.
The code:
from flask import Flask, render_template, redirect, session, json, g
from flask_bootstrap import Bootstrap
from flask.ext.sqlalchemy import SQLAlchemy
from flask.ext.openid import OpenID
import urllib
import re
app = Flask(__name__)
app.secret_key = '123'
Bootstrap(app)
app.config.from_pyfile('settings.cfg')
db = SQLAlchemy(app)
oid = OpenID(app)
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
steam_id = db.Column(db.String(40))
nickname = db.String(80)
#staticmethod
def get_or_create(steam_id):
rv = User.query.filter_by(steam_id=steam_id).first()
if rv is None:
rv = User()
rv.steam_id = steam_id
db.session.add(rv)
return rv
def get_steam_userinfo(steam_id):
options = {
'key': app.config['STEAM_API_KEY'],
'steamids': steam_id
}
url = 'http://api.steampowered.com/ISteamUser/' \
'GetPlayerSummaries/v0001/?%s' % urllib.urlencode(options)
rv = json.load(urllib.urlopen(url))
return rv['response']['players']['player'][0] or {}
_steam_id_re = re.compile('steamcommunity.com/openid/id/(.*?)$')
#app.route('/login')
#oid.loginhandler
def login():
if g.user is not None:
return redirect(oid.get_next_url())
return oid.try_login('http://steamcommunity.com/openid')
#oid.after_login
def create_or_login(resp):
match = _steam_id_re.search(resp.identity_url)
g.user = User.get_or_create(match.group(1))
steamdata = get_steam_userinfo(g.user.steam_id)
g.user.nickname = steamdata['personaname']
db.session.commit()
session['user_id'] = g.user.id
flash('You are logged in as %s' % g.user.nickname)
return redirect(oid.get_next_url())
#app.before_request
def before_request():
g.user = None
if 'user_id' in session:
g.user = User.query.get(session['user_id'])
#app.route('/')
def homepage():
return render_template('mainpage.html')
#app.route('/logout')
def logout():
session.pop('user_id', None)
return redirect(oid.get_next_url())
if __name__ == '__main__':
app.run(debug=True)
You need to run a db.create_all() before running your app.
This will create all the tables described by your model in the database.
If you are new to flask you can follow the quickstart quide here

Categories

Resources