Passing Array into SQL query in Python - python

I am following the CS50 of Harvard and I don't want to use CS50 library that they use for lecture purposes, but I could not figure out how to make this code work. A little help would be greatly appreciated
import sqlite3
from flask import Flask, redirect, render_template, request, session
from flask_session import Session
# Configure app
app = Flask(__name__)
# Connect to database
db = sqlite3.connect("store.db",check_same_thread=False)
c = db.cursor()
# Configure sessions
app.config["SESSION_PERMANENT"] = False
app.config["SESSION_TYPE"] = "filesystem"
Session(app)
#app.route("/")
def index():
books = db.execute("SELECT * FROM books")
list =[dict(id=book[0], title=book[1]) for book in books.fetchall() ]
return render_template("books.html", books=list)
#app.route("/cart", methods=["GET", "POST"])
def cart():
# Ensure cart exists
if "cart" not in session:
session["cart"] = []
# POST
if request.method == "POST":
id = request.form.get("id")
if id:
session["cart"].append(id)
return redirect("/cart")
# GET
books = db.execute("SELECT * FROM books WHERE id IN (?)", [session("cart")])
list =[dict(id=book[0], title=book[1]) for book in books.fetchall()]
return render_template("cart.html", books=list)
The error is at the books=db.execute... line.
Error is :
sqlite3.ProgrammingError: Incorrect number of bindings supplied. The current statement uses 1, and there are 9 supplied
I pressed the cart button 9 times, it is incrementing. Tried other solutions, could not still figure out.

books = db.execute("SELECT * FROM books WHERE id IN (?)", [session("cart")])
should be
query = f"SELECT * FROM books WHERE id IN ({','.join(['?'] * len(session['cart']))})"
books = db.execute(query,session['cart'])))

Related

Type Error: The function either returned None or ended without a return statement

I am currently struggling to get my program working. What I am doing is connecting my database, which is a MySQL database on the workbench, and connecting it to my python. I am trying to store the user inputs as parameters in the stored procedure in my workbench. So when I hit submit the program will take the user input as parameters using the stored procedure. But I am running into several errors. The recurring one being this specific type of error.
Error Message : TypeError: The view function for 'signIn' did not return a valid response. The function either returned None or ended without a return statement.
Python Imports/Code:
from flask import Flask, app, render_template, url_for, request, redirect
import MySQL.connector, CGI
form = cgi.FieldStorage()
app = Flask(__name__)
#app.route('/')
def home():
return "<a href='/login'> login </a><br> <a href='/sign-up'> sign-up </a>"
#app.route('/sign-up', methods=["POST", "GET"])
def signIn():
condition = 0
mydb = mysql.connector.connect(host='localhost', database='signlogpy', user='root', password='thereaper1999',
port="3306")
cursor = mydb.cursor()
if request.method == "POST":
email = request.form["email"]
password = request.form["password"]
name = request.form["name"]
displayName = request.form["displayName"]
DOB = request.form["dateOfBirth"]
args = [email, password, name, displayName, DOB]
else:
return print("Could not reveice user input")
if condition == 0:
condition = 1
elif condition == 1:
results = cursor.callproc('signInInformation', args)
cursor.execute('select * from signin')
cursor.fetchall()
else:
return render_template("SignUp.html")
signInInformationProc = cursor.callproc('signInInformation', args)
results = cursor.fetchall()
print(results)
if results == True:
print("works")
redirect(url_for('login'))
else:
render_template("SignUp.html")
return redirect(url_for(login))
#app.route('/login')
def login():
return render_template('Login.html')
if __name__ == '__main__':
app.run(debug=True)
Workbench MySql code:
use signlogpy;
DELIMITER $$
create procedure signInInformation
(
in
p_userEmail varchar(45),
p_userPassword varchar(45),
p_name varchar(45),
p_displayName varchar(45),
p_dob date
)
begin
insert into signin (userEmail, userPassword, name, displayName, dob)
values (p_userEmail, p_userPassword, p_name, p_displayName, p_dob);
end $$
DELIMITER ;
Any help would be greatly appreciated. If anybody does reply I do thank you immensely and appreciate your help. Thanks in advance!
It looks like the declaration of args is inside
if request.method == "POST":
which means that args doesn't have any meaning outside and after that if statement. Try putting
args = []
at the beginning of signIn() which will let it be accessible by the whole function.

Error in query, response is that row exists but value is None

I creating my first bot using Flask, Twilio, Dialogflow to be deployed at Heroku. My local development is using SQLite but final version should use POSTGRES.
Yesterday as I began to store data to local db, I started getting this error as I try to identify the user that is sending message.
The idea is that, after user is created at db, I will store every message that he sent and every response given by dialogflow. But even though the user is being created at my db, I'm failing to query for his user_id afterwards.
Since it's not an actual error, but not finding the user, I'm posting the code below and printing some parts of it that I'm being trying to use to debug.
CODE:
import os
from flask import Flask, request
from flask_sqlalchemy import SQLAlchemy
from twilio.twiml.messaging_response import MessagingResponse
from sportsbot.utils import fetch_reply
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///myDB.db' #path to database and its name
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False #supress warning of changes on database
db = SQLAlchemy(app)
#app.debug = True
from sportsbot.models import User, Team, Matches, Messages
#app.route('/')
def hello():
return "hello world!"
#app.route('/whatsapp', methods=['POST'])
def sms_reply():
"Check if user is new, create user at db if it is"
phone_no = int(request.form.get('From').split(':')[1][1:])
if User.query.filter(User.user_phone_no == phone_no).count() == 0:
user = User(user_phone_no=phone_no)
db.session.add(user)
db.session.commit()
print("New user")
else:
print("User already at base")
#tring to debug
print(phone_no)
user_id = User.query.filter(User.user_phone_no == phone_no).first()
print(user_id)
msg = request.form.get('Body')
reply = fetch_reply(msg,phone_no)
"Reply to it"
print(reply['text'])
print(reply['intent'])
resp = MessagingResponse()
resp.message(reply['text'])
#message = Messages(user_id = user_id, message= msg, response=reply['text'],intent=reply['intent'])
#db.session.add(message)
#try:
# db.session.commit()
#except:
# db.session.rollback()
return str(resp)
if __name__ == "__main__":
app.run(debug=True)
User class:
class User(db.Model):
user_id = db.Column(db.Integer, primary_key=True)
user_name = db.Column(db.String(80), index = True, unique = False)
user_phone_no = db.Column(db.Integer, index = True, unique = True)
team_id = db.Column(db.Integer, db.ForeignKey('team.team_id'))
def __repr__(self):
return "{}".format(self.user_name)
Prints:
User already at base
5511990046548
None
Oi! Bem Vindo ao EsporteBot. VocĂȘ gostaria de saber sobre algum time ou quer a agenda de eventos da semana?
Default Welcome Intent
Any idea of what I'm doing wrong since it sees the user at db but cannot find it afterwards?
This code
User.query.filter(User.user_phone_no == phone_no).count()
finds 1 user
This code
user_id = User.query.filter(User.user_phone_no == phone_no).first()
gives None as answer
Code works correctly.
Problem is that in model User you created own __repr__() which displays user_name but you don't add user_name to database so it uses None as user_name and when you run first() then this __repr__() prints None as user_name - and this is why you get None on screen.
When you use
def __repr__(self):
return "name: {}".format(self.user_name)
then you get name: None instead of None
Maybe better use
def __repr__(self):
return "id: {}, name: {}, phone no: {}".format(self.user_id, self.user_name, self.user_phone_no)
to get more information.
Or simply remove __repr__ from your model and then you will see something like <User 1>
Minimal working example which everyone can execute:
import os
from flask import Flask, request, render_template_string
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///myDB.db' #path to database and its name
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False #supress warning of changes on database
db = SQLAlchemy(app)
db.create_all()
class User(db.Model):
user_id = db.Column(db.Integer, primary_key=True)
user_name = db.Column(db.String(80), index = True, unique = False)
user_phone_no = db.Column(db.Integer, index = True, unique = True)
def __repr__(self):
#return "{}".format(self.user_name)
#return "name: {}".format(self.user_name)
return "id: {}, name: {}, phone no: {}".format(self.user_id, self.user_name, self.user_phone_no)
#db.create_all()
#app.route('/')
def hello():
return render_template_string("""
<form method="POST" action="/whatsapp">
Phone <input name="From" value="James Bond:+007"></input>
<button type="submit">OK</button>
</form>
""")
#app.route('/whatsapp', methods=['POST'])
def sms_reply():
"Check if user is new, create user at db if it is"
parts = request.form.get('From').split(':')
user_name = parts[0]
phone_no = int(parts[1][1:])
if User.query.filter(User.user_phone_no == phone_no).count() == 0:
#user = User(user_phone_no=phone_no)
user = User(user_phone_no=phone_no, user_name=user_name)
db.session.add(user)
db.session.commit()
print("New user")
else:
print("User already at base")
#tring to debug
print('phone_no:', phone_no)
user = User.query.filter(User.user_phone_no == phone_no).first()
print('user:', user)
return render_template_string("""{{user}}""", user=user)
if __name__ == "__main__":
app.run(debug=True)

Flask and Sqlite3 INSERT works only locally

im working with Flask and Sqlite3.and i've written a code which inserts 3 value into a sqlite3 database.
from flask import Flask, render_template, g, request, redirect, url_for, flash, session
from functools import wraps
from flask_bootstrap import Bootstrap
from wtforms import Form, StringField, PasswordField, DateTimeField
from wtforms.validators import InputRequired
import os
import sqlite3
from datetime import datetime
app = Flask(__name__)
Bootstrap(app)
app.secret_key = os.urandom(24)
app.config.from_object(__name__)
D_candata = '/var/www/FlaskApp/py/static/database/CANData.db'
D_acc = '/var/www/FlaskApp/py/static/database/acc.db'
D_appo ='/var/www/FlaskApp/py/static/database/appo.db'
class LoginForm(Form):
username = StringField(validators=[InputRequired(message='Username ist noch leer')])
password = PasswordField(validators=[InputRequired(message='Password ist noch leer')])
class DateForm(Form):
bdt = DateTimeField(validators=[InputRequired(message='Bitte eingeben')], format = '%d-%m-%Y %H:%M' )
edt = DateTimeField(validators=[InputRequired(message='Bitte eingeben')], format = '%d-%m-%Y %H:%M' )
def connect_db(db):
return sqlite3.connect(db)
def loggin_required(funct):
#wraps(funct)
def wrap(*args, **kwds):
if 'logged_in' in session:
return funct(*args, **kwds)
else:
flash('log in!!')
return redirect(url_for('login'))
return wrap
#app.route('/')
#loggin_required
def index():
g.db = connect_db(D_candata)
cur = g.db.execute('SELECT * FROM CANData LIMIT 1;')
data = [dict(Timestamp=row[0], BatteryVoltage=row[1], BatteryAmperage=row[2], BatteryLoad=row[3], Range=row[4], Speed=row[5], Mileage=row[6]) for row in cur.fetchall()]
g.db.close()
return render_template ("/html/index.html", data=data)
#app.route('/reservierung/', methods = ["GET","POST"])
#loggin_required
def reservie():
form = DateForm(request.form)
b_date = ""
e_date = ""
if request.method == "POST" and form.validate() :
b_date = form.bdt.data
e_date = form.edt.data
if b_date > e_date :
flash('Bitte den Zeitraum korrigieren ')
else:
account = 'admin'
try:
con = connect_db(D_appo)
cur = con.cursor()
flash('ok1')
cur.execute("INSERT INTO appo_info (account, b_date, e_date) VALUES (?, ?, ?)",(account, b_date, e_date)) #???
flash('ok')
con.commit()
con.close()
except:
flash('500')
con.rollback()
return render_template('/html/reservie.html', form=form)
if __name__ == "__main__":
app.run(debug=True)
i think the problem start with
def reservie():
...
cur.execute("INSERT INTO appo_info (account, b_date, e_date) VALUES (?, ?, ?)",(account, b_date, e_date))
because i've use flash and try to show where it goes wrong.
and it just show ('ok1')and ('500') when i use chrome at computer(server is raspberry).
but it did show ('ok') when i tested it at raspberry. and the datas shows in database.
At raspberry pi I can read and write. But at computer i can only read
Im sure is it not the problem from Authentication. The databases and others is already '777'
i cant use debug mode, because it is not local. so did anyone have an idea?
thx a lot

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

Pagination with PyMongo and Flask

I found here a nice template for a pagination. However, this example was done with SQLlite, but I rewrote in order to be able to use PyMongo.
This script creates users and save them to MongoDB with help of PyMongo:
import sys
from pymongo import MongoClient
def fill_data(users_no):
for i in range(users_no):
doc = {
'_id': str(i),
'uname': "name_" + str(i),
}
sDB.insert(doc)
if __name__ == '__main__':
db = MongoClient().test
sDB = db.users
fill_data(1000)
I modified the orginal app.py script in onrder to be able to use PyMongo. This is the modified script:
#!/usr/bin/env python
#-*- coding: utf-8 -*-
from __future__ import unicode_literals
from flask import Flask, render_template, g, current_app, request
from flask.ext.paginate import Pagination
from pymongo import MongoClient
app = Flask(__name__)
app.config.from_pyfile('app.cfg')
#app.route('/')
def index():
db_name = "test"
col_name = "users"
db = MongoClient()
sDB = db[db_name][col_name]
total = sDB.find().count()
print total
page, per_page, offset = get_page_items()
users = sDB.find().skip(offset).limit(per_page)
for u in users:
print u
pagination = get_pagination(page=page,
per_page=per_page,
total=total,
record_name=users,
)
return render_template('index.html', users=users,
page=page,
per_page=per_page,
pagination=pagination,
)
def get_css_framework():
return current_app.config.get('CSS_FRAMEWORK', 'bootstrap3')
def get_link_size():
return current_app.config.get('LINK_SIZE', 'sm')
def show_single_page_or_not():
return current_app.config.get('SHOW_SINGLE_PAGE', False)
def get_page_items():
page = int(request.args.get('page', 1))
per_page = request.args.get('per_page')
if not per_page:
per_page = current_app.config.get('PER_PAGE', 10)
else:
per_page = int(per_page)
offset = (page - 1) * per_page
return page, per_page, offset
def get_pagination(**kwargs):
kwargs.setdefault('record_name', 'records')
return Pagination(css_framework=get_css_framework(),
link_size=get_link_size(),
show_single_page=show_single_page_or_not(),
**kwargs
)
if __name__ == '__main__':
app.run(debug=True)
Is there a way to avoid to use count() by clicking to the next or previous page in the pagination menu?
What did I forget to change so the actual user get be shown in the browser, because currently I only get the pagination menu without users?
User this link, It w'll help to paginate datas using flask-paginate
https://harishvc.com/2015/04/15/pagination-flask-mongodb/
if you are not using Flask use:
https://scalegrid.io/blog/fast-paging-with-mongodb/
Hope it will help !

Categories

Resources