sqlite on dreamhost via flask/JSON - getting 404s - python

I've got a flask app that queries a sqlite database and returns a list to html via jsonify. It works fine on localhost, but I've uploaded to dreamhost and am getting 404s for the jsonified lists. I can't tell whether it is an issue with flask communicating with my sqlite database, flask, or with json.
Here is the flask app:
#!/usr/bin/python
import sqlite3 as sqlite
import json
from flask import Flask, g, jsonify, make_response, render_template
DEBUG = True
DATABASE = './whdt_combined.db'
#setup flask application
app = Flask(__name__)
app.config.from_object(__name__)
##########################
### DATABASE STUFF #######
##########################
#connect to the database
def connect_db():
rv = sqlite.connect(app.config['DATABASE'])
rv.row_factory = dict_factory
return rv
#function for making rows nice
def dict_factory(cursor, row):
d = {}
for idx, col in enumerate(cursor.description):
d[col[0]] = row[idx]
return d
#open new db connection if ones hasn't been opened
def get_db():
if not hasattr(g, 'sqlite_db'):
g.sqlite_db = connect_db()
return g.sqlite_db
#when application stops, close db connection
#app.teardown_appcontext
def close_db(error):
if hasattr(g, 'sqlite_db'):
g.sqlite_db.close()
#easy function to nicely query the db
def query_db(query, args=(), one =False):
cur = get_db().execute(query, args)
rv = cur.fetchall()
cur.close()
return (rv[0] if rv else None) if one else rv
##########################
### APPLICATION ##########
##########################
#app.route('/')
def index():
return render_template('index.html')
#app.route('/<data1>/<data2>/<region>/<year>/1/')
def datafunction1(data1, data2, region, year):
data = []
for row in query_db('SELECT ccode, country, year, region, ' + data1 + ' FROM whdt WHERE year = ' + year + ' AND region = "' + region + '" AND ' + data1 + ' != "" AND ' + data1 + ' > 0 AND ' + data1 + ' < 100 ORDER BY ' + data1 + ' DESC'):
countrywhole = {
'country' :row['country'],
'ccode':row['ccode'],
'year':row['year'],
'region':row['region'],
data1:row[data1]
}
data.append(countrywhole)
return jsonify( { 'data': data } )
if __name__ == '__main__':
app.run()
And here is my folder setup:
/home/user/mydomain.com/myapp/whdt_combined.db
/home/user/mydomain.com/myapp/myapp.py
/home/user/mydomain.com/myapp/__init__.py
/home/user/mydomain.com/myapp/templates/index.html
/home/user/mydomain.com/myapp/static/a couple of css and js files
Flask is not having trouble rendering index.html. Part of the issue is I don't know how to debug through dreamhost. I'm fairly new to this stuff so I'm sorry if I am missing something obvious or otherwise clearly don't know what I'm talking about. Please let me know if I should be providing other important information here. And thanks in advance for your help!

Related

internal server error after submitting a form flask,sqlite3 [duplicate]

This question already has answers here:
Flask view return error "View function did not return a response"
(3 answers)
Closed last year.
I inserted new record from the form, the data will be successfully added into database, but it will show an error page "INTERNAL SERVER ERROR", if I manually back to my form page and refresh i can see the inserted data, but i want it refresh it self and don't show the error page, how to do that?
from flask import Flask, render_template, request
import sqlite3
app = Flask(__name__)
db_name = 'crm.db'
#app.route('/')
def index():
title = "主页"
return render_template("index.html", title = title)
#app.route('/company', methods = ['POST','GET'])
def company():
if request.method == 'GET':
title = "公司"
company_db = query_company()
return render_template("company.html", title = title, company_db = company_db)
else:
insert_company()
def query_company():
connection = sqlite3.connect(db_name)
c = connection.cursor()
c.execute("""SELECT * FROM company""")
company_db = c.fetchall()
return company_db
def insert_company():
connection = sqlite3.connect(db_name)
c = connection.cursor()
query = 'INSERT INTO company(company_full_name, company_short_name) VALUES(?,?)'
cfn = request.form.get("cfn")
csn = request.form.get("csn")
company_info = (cfn,csn)
c.execute(query, company_info)
connection.commit()
connection.close()
if __name__ == '__main__':
app.run(debug = True)
Change the company function to ...
def company():
if request.method == 'POST':
insert_company()
title = "公司"
company_db = query_company()
return render_template("company.html", title = title, company_db = company_db)
This way the new data will first be inserted and then all rows will be automatically refreshed

Flask Returns empty json

Trying to build a simple Flask app from a tutorial.
At this stage, trying to initiate a successful request from the console that posts new data in my database. I'm running my server in one window via app.py then initiating requests in a console window like this:
requests.post("http://localhost:5000/todo", json={"Title":"my first todo", "Description":"my first todo"})
Expecting to see that output rendered when I visit http://localhost:5000/todo. The server shows a code 200, but when I access the site the json is empty: []
app.py:
from flask import Flask, request, jsonify
from models import Schema
from service import ToDoService
import json
app = Flask(__name__)
#app.route("/todo", methods=["POST"])
def create_todo():
return jsonify(ToDoService().create(request.get_json()))
#app.route("/todo", methods=["GET"])
def list_todo():
return jsonify(ToDoService().list())
if __name__ == "__main__":
Schema()
app.run(debug=True)
models.py:
import sqlite3
class Schema:
def __init__(self):
self.conn = sqlite3.connect('todo.db')
self.create_user_table()
self.create_to_do_table()
def create_to_do_table(self):
class ToDoModel:
global TABLENAME
TABLENAME = "Todo"
def __init__(self):
self.conn = sqlite3.connect('todo.db')
def get_by_id(self, _id):
where_clause = f"AND id={_id}"
return self.list_items(where_clause)
def create(self, text, description):
query = f'insert into {TABLENAME} ' \
f'(Title, Description) ' \
f'values ("{text}","{description}")'
result = self.conn.execute(query)
return self.get_by_id(result.lastrowid)
def select(self, text, description):
query = f'values ("{text}","{description}")'
result = self.conn.execute(query)
return result
def list_items(self, where_clause=""):
query = f"SELECT id, Title, Description, DueDate, _is_done " \
f"from {TABLENAME} WHERE _is_deleted != {1} " + where_clause
#print (query)
result_set = self.conn.execute(query).fetchall()
result = [{column: row[i]
for i, column in enumerate(result_set[0].keys())}
for row in result_set]
return result
service.py:
from models import ToDoModel
class ToDoService:
def __init__(self):
self.model = ToDoModel()
def create(self, params):
result = self.model.create(params["Title"], params["Description"])
return result
def update(self, item_id, params):
return self.model.update(item_id, params)
def list(self):
response = self.model.list_items()
return response

Pass username to flask and retrieve the data using sqlite3

So I have just started studying on flask and am just moving to database with flask. I have a database "testdatabase.db" with a table named "Students". What I want to do is. When i pass a username onto the url I need the details of the that specific row.
Here is my python code
from flask import Flask, render_template, request
import sqlite3
conn = sqlite3.connect('testdatabase.db')
c = conn.cursor()
app = Flask(__name__)
#app.route("/students/<name>")
def students(name):
return jam()
def jam():
c.execute("select * from students where name = '" + name + "'")
print(c.fetchall())
conn.close()
if __name__ == "__main__":
app.run(debug=True)
The error being shown is that name 'name' is not defined. How do I define the name to be passed to the url?
Name is being passed correctly to the url
#app.route("/students/<name>")
def students(name):
return jam()
Your only problem is that you are not passing it to the jam function
solution
#app.route("/students/<name>")
def students(name):
return jam(name)
def jam(name):
c.execute("select * from students where name = '" + name + "'")
print(c.fetchall())
conn.close()
# Return the data jsonfied.
There is no variable 'name' in jam, try:
from flask import Flask, render_template, request
import sqlite3
conn = sqlite3.connect('testdatabase.db')
c = conn.cursor()
app = Flask(__name__)
#app.route("/students/<name>")
def students(name):
return jam(name)
def jam(name):
c.execute("select * from students where name = '" + name + "'")
print(c.fetchall())
conn.close()
if __name__ == "__main__":
app.run(debug=True)

OperationalError: no such table: books on python anywhere

I have a file structure on python anywhere as :
flaskhost(folder) which contains :
app.py
books.db
app.py contains -:
import flask
from flask import request, jsonify
import sqlite3
app = flask.Flask(__name__)
app.config["DEBUG"] = True
def dict_factory(cursor, row):
d = {}
for idx, col in enumerate(cursor.description):
d[col[0]] = row[idx]
return d
#app.route('/', methods=['GET'])
def home():
return '''<h1>Distant Reading Archive</h1>
<p>A prototype API for distant reading of science fiction novels.</p>'''
#app.route('/api/v1/resources/books/all', methods=['GET'])
def api_all():
conn = sqlite3.connect('books.db')
conn.row_factory = dict_factory
cur = conn.cursor()
all_books = cur.execute('SELECT * FROM books;').fetchall()
return jsonify(all_books)
#app.errorhandler(404)
def page_not_found(e):
return "<h1>404</h1><p>The resource could not be found.</p>", 404
#app.route('/api/v1/resources/books', methods=['GET'])
def api_filter():
query_parameters = request.args
id = query_parameters.get('id')
published = query_parameters.get('published')
author = query_parameters.get('author')
query = "SELECT * FROM books WHERE"
to_filter = []
if id:
query += ' id=? AND'
to_filter.append(id)
if published:
query += ' published=? AND'
to_filter.append(published)
if author:
query += ' author=? AND'
to_filter.append(author)
if not (id or published or author):
return page_not_found(404)
query = query[:-4] + ';'
conn = sqlite3.connect('books.db')
conn.row_factory = dict_factory
cur = conn.cursor()
results = cur.execute(query, to_filter).fetchall()
return jsonify(results)
if __name__ == '__main__':
app.run()
I am trying to follow this tutorial
https://programminghistorian.org/en/lessons/creating-apis-with-python-and-flask
my site is hosted at :
http://vivanks.pythonanywhere.com
But when I call api by
http://127.0.0.1:5000/api/v1/resources/books?author=Connie+Willis
It show me error :
sqlite3.OperationalError: no such table: books
Any help how to fix this and host app on pythonanywhere.com ?
P.S On my local machine it's working perfectly fine
On Pythonanywnere, When pointing to content other than templates or static files (stored in their own proper directories, accessible by flask), you have to provide the full path:
conn = sqlite3.connect('/home/your_username/flaskhost/books.db')

nginx uwsgi bottle postgresql psycopg2

My requirement:
About 300 (field sensor-like) clients report their status (json string) once every X (say 10) minutes. They can only use "curl" to do the reporting . The API/handler on the server needs to parse and dump all those values into the master table.
A few users (usually less than 10) connect to the app from their browsers to check the status of the sensor-reports and may linger around checking a few pages (main status page, detailed report page etc.). There are less than 10 pages (think reports) that the users want to see.
My setup:
Web Server: nginx
App Server: uwsgi
Framework: Bottle
Database: PostgreSQL
Python DB Driver: psycopg2
Frontend: Bootstrap
My code:
Please note that I did not include a lot of error checking and other security measures that we have in code, simply because they do not contribute to this discussion.
import os
from bottle import route, post, run, request, template, install, static_file
import psycopg2
import customemailservice
#route('/static/<filepath:path>')
def server_static(filepath):
return static_file(filepath, root='/webapp/ss/static')
# The URL that the sensors will hit to pass on their status report
#post('/logger')
def dolog():
sensor_id = request.json['id']
sensor_ts = request.json['ts']
sensor_ut = request.json['main']['ut']
sensor_ploss = request.json['main']['ploss']
sensor_s1 = request.json['main']['s1']
sensor_s2 = request.json['main']['s2']
sensor2_status = request.json['aux']['status']
sensor2_rts = request.json['aux']['rts']
try:
conn = psycopg2.connect('dbname=<dbnane> user=<username> password= <password> host=<dbhost> port=<dbport>')
except psycopg2.Error as pe:
print pe.pgerror
curr = conn.cursor()
if conn != None and curr != None:
curr.execute('''INSERT INTO tbllog (id, ts, ut, ploss, s1, s2, status, rts) VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s)''',(sensor_id, sensor_ts, sensor_ut, sensor_ploss, sensor_s1, sensor_s2, sensor2_status, sensor2_rts))
conn.commit()
curr.close()
conn.close()
else:
pass
# The code here is irrelevant
return template('Ok from {{sid}} at {{ts}}', sid=sid,ts=ts)
#route('/')
def index():
try:
conn = psycopg2.connect('dbname=<dbnane> user=<username> password=<password> host=<dbhost> port=<dbport>')
except psycopg2.Error as pe:
conn = None
print pe.pgerror
curr = conn.cursor()
if conn != None and curr != None:
sql = 'select t1.* from tbllog t1 where t1.ts = (select max(t2.ts) from tbllog t2 where t2.id=t1.id) order by id;'
curr.execute(sql)
rs=curr.fetchall()
html=""
for row in rs:
html = html + '<tr><td class="warning">' + row[0] + '</td><td class="warning">' + str(row[1]) + '</td><td class="success">' + str(row[2]) + '</td><td class="success">' + str(row[3]) + '</td><td class="success">' + str(row[4]) + '</td><td class="info">' + str(row[5]) + '</td><td class="info">' + str(row[6]) + '</td></tr>'
curr.close()
conn.close()
# Pass the raw html table that will be inserted into the index template.
return template('index',tdata=html)
#route('/status/<sensor_id>')
def getsensorid(sensor_id):
try:
conn = psycopg2.connect('dbname=<dbnane> user=<username> password=<password> host=<dbhost> port=<dbport>')
except psycopg2.Error as pe:
conn = None
print pe.pgerror
curr = conn.cursor()
if conn != None and curr != None:
sql = 'select * from tbllog where id=\'' + sensor_id + '\' order by ts;'
curr.execute(sql)
rs=curr.fetchall()
html=""
for row in rs:
html = html + '<tr class="info"><td>' + row[0] + '</td><td>' + str(row[1]) + '</td><td>' + str(row[2]) + '</td><td>' + str(row[3]) + '</td><td>' + str(row[4]) + '</td><td>' + str(row[5]) + '</td><td>' + str(row[6]) + '</td></tr>'
curr.close()
conn.close()
if __name__ == '__main__':
run (host="0.0.0.0", port=8080, debug=True)
else:
app = application = bottle.default_app()
My Question:
Given the requirements, is this a reasonable approach? Or, do you recommend I use DB connection pooling? I am a little confused about using pooling since I am not sure at what level (nginx, uwsgi or bottle) does my app code get duplicated (to serve concurrent clients) and how should I go about creating the pool that I can use across different threads/processes (each of which contain a copy of this app code).
Obviously, this is my initial foray into web apps (and even serious Python for that matter) and would like to hear back from you if you think there is a better (I'm assuming there are many) ways to skin the cat.

Categories