This is my file structure:
server.py (the flask app)
regione.py (class model)
provincia.py (class model)
comune.py (class model)
Image Example
The code:
server.py
from flask import Flask, jsonify
from flask_cors import CORS
from flask_sqlalchemy import SQLAlchemy
from model.regione import Regione
from model.provincia import Provincia
from model.comune import Comune
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///ang_database.sqlite3'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False # per consumare meno memoria, da approfondire
db = SQLAlchemy(app)
CORS(app)
#app.route('/')
def index():
return jsonify('Api per Regioni, Province, Comuni attiva')
#app.route('/regioni')
def get_regioni():
regioni = db.session.query(Regione).all()
#regioni = db.session.execute(db.select(Regione).order_by(Regione.nome)).scalars()
regioni_list = [r.to_dict() for r in regioni]
return regioni_list
#app.route('/province/<string:regione>/')
#app.route('/province/<string:regione>/<string:caratteri>')
def get_province(regione:str, caratteri:str|None=None):
if caratteri is None:
province = db.session.query(Provincia).filter(Provincia.regione == regione).all()
province_list = [p.to_dict() for p in province]
else:
province = db.session.query(Provincia).filter(Provincia.regione == regione, Provincia.nome.ilike('%'+caratteri+'%')).all()
province_list = [p.to_dict() for p in province]
return province_list
#app.route('/comuni/<string:provincia>/')
#app.route('/comuni/<string:provincia>/<string:caratteri>')
def get_comuni(provincia:str, caratteri:str|None=None):
if caratteri is None:
comuni = db.session.query(Comune).filter(Comune.provincia == provincia).all()
comuni_list = [p.to_dict() for p in comuni]
else:
comuni = db.session.query(Comune).filter(Comune.provincia == provincia, Comune.nome.ilike('%'+caratteri+'%')).all()
comuni_list = [p.to_dict() for p in comuni]
return comuni_list
if __name__ == '__main__':
app.run(port=9000)
regioni.py
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
class Regione(db.Model):
__tablename__ = 'regione'
nome = db.Column(db.String, primary_key=True)
def __init__(self, nome):
self.nome = nome
def __repr__(self):
return f'{self.nome}'
def to_dict(self):
return {'nome': self.nome}
Database is generated with other tests with SqlAlchemy only:
Database sample
I tried renaming database to "ang_database.db" too
The problem:
sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) no such table: regione
[SQL: SELECT regione.nome AS regione_nome FROM regione]
Should I use "app.app_context()" and "db.create_table()" somewhere?
What am I missing? I think I'm confusing SqlAlchemy and Flask_SqlAlchemy or I'm ignoring something stupid, hope u can help, thank you.
Related
I am trying to make a website that allows a user to create their own "to-watch" list and also can randomly select a title from the created list, showing the movie's plot, genre, and IMDb rating using an API. I've encountered a "NoneType' object is not subscriptable" error message when trying to run this function and am not sure how to overcome it. Here are the relevant parts of my code:
application.py
import os
from cs50 import SQL
from flask import Flask, flash, jsonify, redirect, render_template, request, session
from flask_session import Session
from tempfile import mkdtemp
from werkzeug.exceptions import default_exceptions, HTTPException, InternalServerError
from werkzeug.security import check_password_hash, generate_password_hash
from helpers import apology, login_required, imdb
app = Flask(__name__)
app.config["TEMPLATES_AUTO_RELOAD"] = True
#app.after_request
def after_request(response):
response.headers["Cache-Control"] = "no-cache, no-store, must-revalidate"
response.headers["Expires"] = 0
response.headers["Pragma"] = "no-cache"
return response
app.config["SESSION_FILE_DIR"] = mkdtemp()
app.config["SESSION_PERMANENT"] = False
app.config["SESSION_TYPE"] = "filesystem"
Session(app)
db = SQL("sqlite:///project.db")
#app.route("/select", methods=["GET", "POST"])
#login_required
def select():
if request.method == "POST":
"""Randomly pick a movie to watch"""
therearemovies = db.execute("SELECT uniqueid FROM movies WHERE id=:id", id=session["user_id"])
if therearemovies:
chosen = db.execute("SELECT * FROM movies WHERE id=:id ORDER BY RANDOM() LIMIT 1", id=session["user_id"])
for uniqueindex in chosen:
suggestion = uniqueindex["title"]
**info = imdb(suggestion)
plot = info["plot"]
genre = info["genre"]
rating = info["rating"]**
return render_template("select.html", suggestion=suggestion, plot=plot, genre=genre, rating=rating)
else:
return apology("You don't have any movies in your list")
else:
return render_template("/")
helper.py:
import os
import requests
import urllib.parse
def imdb(title):
try:
response=requests.get(f"http://www.omdbapi.com/?t={urllib.parse.quote_plus(title)}&apikey=12345678")
response.raise_for_status()
except requests.RequestException:
return None
try:
data = response.json()
return
{
"plot": data["plot"],
"genre": data["genre"],
"rating": data["imdbRating"]
}
except (KeyError, TypeError, ValueError):
return None
Error Message:
File "/home/ubuntu/finalproject/helpers.py", line 32, in decorated_function
return f(*args, **kwargs)
File "/home/ubuntu/finalproject/application.py", line 126, in select
plot = info["plot"]
TypeError: 'NoneType' object is not subscriptable
When querying a table, I'd like to eager load a set of columns. Prior to 1.3.x, I could do it with the below code, but it now I'm getting:
sqlalchemy.exc.ArgumentError: Attribute "AliasedClass_Blueprint.engineer" does not link from element "mapped class
Blueprint->blueprints". Did you mean to use Building.blueprint.of_type(AliasedClass_Blueprint)?
The query in question is setup as follows:
def doQuery():
building = aliased(Building)
blueprint = aliased(Blueprint, name="blueprint")
engineer = aliased(Engineer, name="engineer")
with sessionScope() as session:
return session.query(building)\
.join(blueprint, blueprint.id==building.blueprintId)\
.outerjoin(engineer, blueprint.engineerId==engineer.id)\
.options(contains_eager(building.blueprint, alias=blueprint))\
.options(contains_eager(building.blueprint, alias=blueprint)\
# The error shows up here
.contains_eager(blueprint.engineer, alias=engineer))
The error suggests using building.blueprint.of_type(blueprint), which seems to work properly, but it looks to be accomplishing something similar to what alias=blueprint does. Does of_type(x) replace the alias=x parameter?
Below is a functioning example with both a working function and one that reproduces the error:
from sqlalchemy import create_engine, inspect, Column, Integer, String, DateTime, ForeignKey
from sqlalchemy.orm import sessionmaker, relationship, aliased, contains_eager
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class Engineer(Base):
__tablename__ = "engineers"
id=Column(Integer, primary_key=True)
name=Column(String)
def __repr__(self):
return self.name
class Blueprint(Base):
__tablename__ = "blueprints"
id=Column(Integer, primary_key=True)
name=Column(String)
engineerId=Column(Integer, ForeignKey('engineers.id'))
engineer=relationship(Engineer, foreign_keys=[engineerId], backref="outputBlueprints")
def __repr__(self):
return self.name
class Building(Base):
__tablename__ = "buildings"
id=Column(Integer, primary_key=True)
name=Column(String)
blueprintId=Column(Integer, ForeignKey('blueprints.id'))
blueprint = relationship(Blueprint, foreign_keys=[blueprintId], remote_side=[Blueprint.id], backref='buildings')
def __repr__(self):
return self.name
engine = create_engine('sqlite:///:memory:', echo=True)
Base.metadata.create_all(engine)
sessionFactory = sessionmaker(bind=engine, expire_on_commit=False)
#contextmanager
def sessionScope():
try:
session = sessionFactory()
yield session
session.commit()
except Exception as e:
session.rollback()
raise
finally:
session.close()
return
def doQueryWorking():
building = aliased(Building)
blueprint = aliased(Blueprint, name="blueprint")
engineer = aliased(Engineer, name="engineer")
with sessionScope() as session:
return session.query(building)\
.join(blueprint, blueprint.id==building.blueprintId)\
.outerjoin(engineer, blueprint.engineerId==engineer.id)\
.options(contains_eager(building.blueprint.of_type(blueprint)))\
.options(contains_eager(building.blueprint.of_type(blueprint))\
.contains_eager(blueprint.engineer, alias=engineer))
def doQueryError():
building = aliased(Building)
blueprint = aliased(Blueprint, name="blueprint")
engineer = aliased(Engineer, name="engineer")
with sessionScope() as session:
return session.query(building)\
.join(blueprint, blueprint.id==building.blueprintId)\
.outerjoin(engineer, blueprint.engineerId==engineer.id)\
.options(contains_eager(building.blueprint, alias=blueprint))\
.options(contains_eager(building.blueprint, alias=blueprint)\
.contains_eager(blueprint.engineer, alias=engineer))
buildings = doQueryError()
I am desperately trying to do the following:
Capture details of 2 individuals in a Flaskform (i.e. a father and a mother). Each individual is an instance of an Individual class / model and stored in an SQLAlchemy table
When the second individual is added (could be the father or the mother), then a relationship is created with the ids of the two Individuals, in a Parents table. This creates a relationship record between the father and the mother. I'm happy that's all set up OK.
Main app code is below. I want to make sure I can grab both id's at the same time, to create the relationship (hence the print statements).
Yet the first time I add an individual, two print statements output:
New father ID is 1
New mother ID is None # this is probably expected as I haven't added the second Individual yet
Second time I add an individual, I get:
New father ID is None
New mother ID is 2 # What has happened to the first Individual's ID?
I have tried declaring global variables to write the ids back to but get errors about using a variable before they are declared.
Can anyone help?
from genealogy import app
from flask import render_template, session, redirect, url_for, request
from genealogy import db
from genealogy.models import Individual, Parents
from genealogy.individual.forms import AddIndividual
#app.route("/", methods=["GET", "POST"])
def index():
form = AddIndividual()
def fullname(first, last):
return first + " " + last
if request.method == "POST":
new_father = Individual("",None,None)
new_mother = Individual("",None,None)
new_child = Individual("",None,None)
new_partners = Parents(None,None)
if request.form.get("addfather") == "Add":
father_forenames = form.father_forenames.data
father_surname = form.father_surname.data
father_fullname = fullname(father_forenames, father_surname)
new_father = Individual(father_surname, father_fullname, father_forenames)
db.session.add(new_father)
session["new_father.id"] = new_father.id
db.session.commit()
# db.session.flush()
# if Parents.query.filter_by(father_id=new_father.id, mother_id=new_mother.id):
# pass
# else:
# new_partners = Parents(new_father.id, new_mother.id)
# db.session.add(new_partners)
# db.session.commit()
if request.form.get("addmother") == "Add":
mother_forenames = form.mother_forenames.data
mother_surname = form.mother_surname.data
mother_fullname = fullname(mother_forenames, mother_surname)
new_mother = Individual(mother_surname, mother_fullname, mother_forenames)
db.session.add(new_mother)
session["new_mother.id"] = new_mother.id
db.session.commit()
# db.session.flush()
# if Parents.query.filter_by(father_id=focus_father.id, mother_id=focus_mother.id):
# pass
# else:
# new_partners = Parents(focus_father.id, focus_mother.id)
# db.session.add(new_partners)
# db.session.commit()
if request.form.get("addchild") == "Add":
child_forenames = form.child_forenames.data
child_surname = form.child_surname.data
child_fullname = fullname(child_forenames, child_surname)
new_child = Individual(child_surname, child_fullname, child_forenames)
db.session.add(new_child)
focus_person = new_child
db.session.commit()
print("New father ID is " + str(session["new_father.id"]))
print("New mother ID is " + str(session["new_mother.id"]))
return render_template("home.html", form=form)
# return render_template("home.html", form=form, focus_father=focus_father, focus_mother=focus_mother,
# focus_person=focus_person, focus_partners=focus_partners)
return render_template("home.html", form=form)
if __name__ == "__main__":
app.run(debug=True)
Thanks to #van, here's the working code:
from genealogy import app
from flask import render_template, session, redirect, url_for, request
from genealogy import db
from genealogy.models import Individual, Parents
from genealogy.individual.forms import AddIndividual
#app.route("/", methods=["GET", "POST"])
def index():
form = AddIndividual()
def fullname(first, last):
return first + " " + last
if request.method == "POST":
new_father = Individual("",None,None)
new_mother = Individual("",None,None)
new_child = Individual("",None,None)
new_partners = Parents(None,None)
if request.form.get("addfather") == "Add":
father_forenames = form.father_forenames.data
father_surname = form.father_surname.data
father_fullname = fullname(father_forenames, father_surname)
new_father = Individual(father_surname, father_fullname, father_forenames)
db.session.add(new_father)
db.session.commit()
db.session.flush()
session["new_father.id"] = new_father.id
if request.form.get("addmother") == "Add":
mother_forenames = form.mother_forenames.data
mother_surname = form.mother_surname.data
mother_fullname = fullname(mother_forenames, mother_surname)
new_mother = Individual(mother_surname, mother_fullname, mother_forenames)
db.session.add(new_mother)
db.session.commit()
db.session.flush()
session["new_mother.id"] = new_mother.id
if request.form.get("addchild") == "Add":
child_forenames = form.child_forenames.data
child_surname = form.child_surname.data
child_fullname = fullname(child_forenames, child_surname)
new_child = Individual(child_surname, child_fullname, child_forenames)
db.session.add(new_child)
focus_person = new_child
db.session.commit()
print("New father ID is " + str(session["new_father.id"]))
print("New mother ID is " + str(session["new_mother.id"]))
return render_template("home.html", form=form)
# return render_template("home.html", form=form, focus_father=focus_father, focus_mother=focus_mother,
# focus_person=focus_person, focus_partners=focus_partners)
return render_template("home.html", form=form)
if __name__ == "__main__":
app.run(debug=True)
This is my app.py
import logging.config
import os
from flask import Flask, Blueprint, url_for
from flask_migrate import Migrate
from flask_restplus import Api
from authentek import settings
from authentek.api.blog.endpoints.posts import ns as blog_posts_namespace
from authentek.api.blog.endpoints.categories import ns as blog_categories_namespace
from authentek.api.auth.endpoints.users import ns as users_namespace
from authentek.api.restplus import api
from authentek.database import db
app = Flask(__name__)
logging_conf_path = os.path.normpath(os.path.join(os.path.dirname(__file__), '../logging.conf'))
logging.config.fileConfig(logging_conf_path)
log = logging.getLogger(__name__)
def has_no_empty_params(rule):
defaults = rule.defaults if rule.defaults is not None else ()
arguments = rule.arguments if rule.arguments is not None else ()
return len(defaults) >= len(arguments)
#app.route("/sitemap")
def site_map():
links = []
for rule in app.url_map.iter_rules():
# Filter out rules we can't navigate to in a browser
# and rules that require parameters
if "GET" in rule.methods and has_no_empty_params(rule):
url = url_for(rule.endpoint, **(rule.defaults or {}))
links.append((url, rule.endpoint))
# links is now a list of url, endpoint tuples
def configure_app(flask_app):
flask_app.config['SERVER_NAME'] = settings.FLASK_SERVER_NAME
flask_app.config['SQLALCHEMY_DATABASE_URI'] = settings.SQLALCHEMY_DATABASE_URI
flask_app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = settings.SQLALCHEMY_TRACK_MODIFICATIONS
flask_app.config['SWAGGER_UI_DOC_EXPANSION'] = settings.RESTPLUS_SWAGGER_UI_DOC_EXPANSION
flask_app.config['RESTPLUS_VALIDATE'] = settings.RESTPLUS_VALIDATE
flask_app.config['RESTPLUS_MASK_SWAGGER'] = settings.RESTPLUS_MASK_SWAGGER
flask_app.config['ERROR_404_HELP'] = settings.RESTPLUS_ERROR_404_HELP
def initialize_app(flask_app):
configure_app(flask_app)
blueprint = Blueprint('api', __name__, url_prefix='/api')
# api.init_app(blueprint)
migrate = Migrate(flask_app, db)
api.add_namespace(blog_posts_namespace)
api.add_namespace(blog_categories_namespace)
api.add_namespace(users_namespace)
if blueprint.name not in flask_app.blueprints.keys():
flask_app.register_blueprint(blueprint)
else:
flask_app.blueprints[blueprint.name] = blueprint
print(flask_app.blueprints)
db.init_app(flask_app)
api.init_app(flask_app)
def main():
from authentek.database.models import Post, Category, User, BlacklistToken # noqa
app.config.from_object(settings)
initialize_app(app)
log.info('>>>>> Starting development server at http://{}/api/ <<<<<'.format(app.config['SERVER_NAME']))
app.run(host='0.0.0.0', debug=settings.FLASK_DEBUG)
if __name__ == "__main__":
main()
forget about all the routes, at least /sitemap should work!
This is the problem. I can do count() (the count of this query is 1617) but can't figure out how to do a sum. FWIW, this is from a job satisfaction survey. Lots of 1 and 0 depending on whether they provided a response to a specific question.
This works:
#app.route('/list') def list_respondents(): all_working = Jf_Q1.query.filter((Jf_Q1.working==1) & (Jf_Q1.good_job==1)).count() return render_template('list.html', all_working=all_working)
This code above works, but what I need to be able to replicate this from postgres:
select sum(moderatewellbeing)/sum(good_job) from jf_q1
where working=1
and
good_job=1;
I've tried:
all_working = Jf_Q1.query.filter(Jf_Q1.working==1).sum()
return render_template('list.html', all_working=all_working)
But flask tosses me:
'AttributeError: 'BaseQuery' object has no attribute 'sum'
Here is all my code:
from flask import Flask,render_template, url_for, redirect
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import func
from flask_migrate import Migrate
######################################
#### SET UP OUR SQLite DATABASE #####
####################################
app = Flask(__name__)
app.config['SECRET_KEY'] = 'mysecretkey'
# Connects our Flask App to our Database
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql://postgres:M1keD8nJ0e#localhost:5432/project2'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)
Migrate(app,db)
#####################################
####################################
###################################
# Let's create our first model!
# We inherit from db.Model class
class Jf_Q1(db.Model):
__tablename__ = 'jf_q1'
#########################################
## CREATE THE COLUMNS FOR THE TABLE ####
#######################################
# Primary Key column, unique id for each puppy
id = db.Column(db.Integer,primary_key=True)
respondent_id = db.Column(db.Text)
good_job = db.Column(db.Numeric)
mediocre_job = db.Column(db.Numeric)
bad_job = db.Column(db.Numeric)
highwellbeing = db.Column(db.Numeric)
moderatewellbeing = db.Column(db.Numeric)
lowwellbeing = db.Column(db.Numeric)
working = db.Column(db.Numeric)
# This sets what an instance in this table will have
# Note the id will be auto-created for us later, so we don't add it here!
def __init__(self,respondent_id,good_job,mediocre_job,bad_job,highwellbeing,moderatewellbeing,lowwellbeing,working):
self.respondent_id = respondent_id
self.good_job = good_job
self.mediocre_job = mediocre_job
self.bad_job = bad_job
self.highwellbeing = highwellbeing
self.moderatewellbeing = moderatewellbeing
self.lowwellbeing = lowwellbeing
self.working = working
# def __repr__(self):
#app.route('/')
def index():
return render_template('home.html')
#app.route('/list')
def list_respondents():
# all_working = Jf_Q1.query.filter((Jf_Q1.working==1) & (Jf_Q1.good_job==1)).count()
# return render_template('list.html', all_working=all_working)
all_working = Jf_Q1.query.filter(Jf_Q1.working==1).sum()
return render_template('list.html', all_working=all_working)
# all_working = select([func.sum(Jf_Q1.working)]).\
# where(Jf_Q1.working==1)
# return render_template('list.html', all_working=all_working)
if __name__ == '__main__':
app.run(debug=True)
you can try this:-
from sqlalchemy.sql import func
all_working = session.query(func.sum(Jf_Q1.working)).filter(Jf_Q1.working==1)
or also you can use with_entities
all_working = Jf_Q1.with_entities(func.sum(jf_Q1.working)).filter(Jf_Q1.working==1)