Cannot insert row using Flask and SQLAlchemy - python

I am doing CS50 project and the current task is to create a register page. User fills in the form and presses button. So it has to be insert into my PostgreSQL database. But when I fill the form and press 'Register' I got this error:
StatementError: (sqlalchemy.exc.InvalidRequestError) A value is required for bind parameter u'surname' [SQL: u'INSERT INTO users (name, surrname, nickname, password) VALUES (%(name)s, %(surname)s,%(nickname)s, %(password)s'] [parameters: [{':password': u'', ':name': u'John', ':surname': u'Young', ':nickname': u'yolojohny1'}]] (Background on this error at: http://sqlalche.me/e/cd3x)
books.py
import os
from flask import Flask, session, render_template, request
from flask_session import Session
from sqlalchemy import create_engine
from sqlalchemy.orm import scoped_session, sessionmaker
app = Flask(__name__)
# Check for environment variable
if not os.getenv("DATABASE_URL"):
raise RuntimeError("DATABASE_URL is not set")
# Configure session to use filesystem
app.config["SESSION_PERMANENT"] = False
app.config["SESSION_TYPE"] = "filesystem"
Session(app)
# Set up database
engine = create_engine(os.getenv("DATABASE_URL"))
db = scoped_session(sessionmaker(bind=engine))
#app.route("/")
def index():
return render_template("register.html")
#app.route('/register', methods=["POST"])
def register():
"REGISTRATION PROCESS"
# Get form information
name = request.form.get("name")
surname = request.form.get("surname")
nickname = request.form.get("nickname")
password = request.form.get("password")
db.execute("INSERT INTO users (name, surrname, nickname, password) VALUES (:name, :surname,"
":nickname, :password", {":name": name, ":surname": surname, ":nickname": nickname,
":password": password})
db.commit()
return render_template("success.html")
register.html:
{% extends "layout.html" %}
{% block title %}
New User
{% endblock %}
{% block body %}
<h1>Register new account</h1>
<form action="{{ url_for('register') }}" method="post">
<div class="form-group">
<input class="form-control" name="name" placeholder="First Name">
</div>
<div class="form-group">
<input class="form-control" name="surname" placeholder="Second Name">
</div>
<div class="form-group">
<input class="form-control" name="nickname" placeholder="Nickname">
</div>
<div class="form-group">
<input type="password" class="form-control" name="password" placeholder="Password">
</div>
<div class="formgroup">
<button class="btn btn-primary">Create account!</button>
</div>
</form>
{% endblock %}
database:
CREATE TABLE "users" (
id SERIAL PRIMARY KEY,
name VARCHAR NOT NULL,
surrname VARCHAR NOT NULL,
nickname VARCHAR NOT NULL,
password VARCHAR NOT NULL
)
What should I do? I googled this Error but nothing helps.

you are almost there.
db.execute("INSERT INTO users (name, surrname, nickname, password) VALUES (:name, :surname, :nickname, :password", {":name": name, ":surname": surname, ":nickname": nickname, ":password": password})
Firstly, this doesn't execute as you are missing the closing parenthesis after your VALUES list. So to get the statement to execute I had to make it:
db.execute("INSERT INTO users (name, surrname, nickname, password) VALUES (:name, :surname, :nickname, :password)", {":name": name, ":surname": surname, ":nickname": nickname, ":password": password})
I imagine that is just a typo translating info into the questions, but nonetheless.
Now, the colon (:), prior to the parameter names in your SQL statement is there to tell SQLAlchemy that that name is a bound parameter. You can read more about it here.. You don't need to include that in the keys of your parameter values dict, and that is why you are seeing the error. SQLAlchemy is looking for a parameter named surname but that doesn't exist in your supplied parameter values, :surname does, but ':surname' != 'surname' and so no value can be found for the parameter.
This should get you across the line:
db.execute("INSERT INTO users (name, surrname, nickname, password) VALUES (:name, :surname, :nickname, :password)", {"name": name, "surname": surname, "nickname": nickname, "password": password})

Related

HTML form data not updating in postgres Table throug flask python

Hi i am trying to upload create.html fields data to postgres DB.
My html form code is as below:
<!DOCTYPE html>
{% block content %}
<h1>{% block title %} Add a New Book {% endblock %}</h1>
<form method="post">
<p>
<label for="title">Title</label>
<input type="text" name="title"
placeholder="Book title">
</input>
</p>
<p>
<label for="author">Author</label>
<input type="text" name="author"
placeholder="Book author">
</input>
</p>
<p>
<label for="pages_num">Number of pages</label>
<input type="number" name="pages_num"
placeholder="Number of pages">
</input>
</p>
<p>
<label for="review">Review</label>
<br>
<textarea name="review"
placeholder="Review"
rows="15"
cols="60"
></textarea>
</p>
<p>
<button type="submit">Submit</button>
</p>
</form>
{% endblock %}
Once i enter values in form those values should reflect in my postgres in below DB table
CREATE TABLE sample_schema.books (
id serial PRIMARY KEY,
title text COLLATE pg_catalog."default" NOT NULL,
author text COLLATE pg_catalog."default" NOT NULL,
pages_num integer NOT NULL,
review text COLLATE pg_catalog."default",
date_added date DEFAULT CURRENT_TIMESTAMP
)
and my python code is as follows
import os
import psycopg2
from flask import Flask, render_template
app = Flask(__name__)
def get_db_connection():
conn = psycopg2.connect(user="user",
password="pass123",
host="00.00.0.00",
port="5432",
database="samp_DB")
return conn
from flask import Flask, render_template, request, url_for, redirect
#app.route('/create/', methods=('GET', 'POST'))
def create():
if request.method == 'POST':
title = request.form['title']
author = request.form['author']
pages_num = int(request.form['pages_num'])
review = request.form['review']
conn = get_db_connection()
cur = conn.cursor()
cur.execute('INSERT INTO sample_schema.books (title, author, pages_num, review)'
'VALUES (%s, %s, %s, %s)',
(title, author, pages_num, review))
conn.commit()
cur.close()
conn.close()
return redirect(url_for('index'))
return render_template('D:/create.html')
Once after i ran above code and enter values in html form the fields that i entered in form doesn't updating in book table.
Thanks in advance

flask and sqlite update values that might be empty

I need to update values of a row in my database based on the post request that I receive from a form.
The HTML form will send through the post request some or all the values that will be needed to update a row. and I thought that I should be using UPDATE query to update the values in the row, but the values might be empty which throw a syntax error.
the HTML is:
<form action="/change-profile-information" method="POST">
<label>email</label>
<input type="email" name="email" value={{result[0]}}>
<label>name contact person</label>
<input type="text" name="contact_person" value={{result[1]}}>
<label>phone</label>
<input type="tel" name="phone" value={{result[2]}}>
<label>address</label>
<input type="text" name="address" value={{result[3]}}>
<label>profile image</label>
<input type="file" name="image">
<button type="submit">SUBMIT</button>
</form>
while in my Flask function for the post request I am doing my SQLite query to update the values.
#app.route('/change-profile-information', methods=['POST'])
def change_profile_information():
if 'username' in session:
user_id = session['user_id']
email = request.form.get('email')
first_name = request.form.get('first_name')
last_name = request.form.get('last_name')
phone = request.form.get('phone')
address = request.form.get('address')
image = request.form.get('image')
# change in DB
con = lite.connect('base.db')
cur = con.cursor()
try:
cur.execute(f"""UPDATE farmers
SET email='{email}', name='{first_name}'
lastname='{last_name}',
phone='{phone}', address='{address}',
profile_image='{image}'
WHERE farmer_id='{user_id}';""")
# reload page
return redirect('/settings-farmer.html', code=302)
except lite.Error as error:
return "Failed: "+str(error)
finally:
if (con):
con.close()
In this last piece of code the values of first_name = request.form.get('first_name') might be empty and this gives me a problem. In fact if I send the request with the parameter of last_name it will through an error saying Failed: near "lastname": syntax error. It seems that if the parameter are empty I still have empty strings, but that would still throw a syntax error for SQLite.
Should I be using ? and VALUES('{last_name}') or maybe I should be using REPLACE instead of UPDATE?

Internal Server error in register html page

I am trying to create a register page for a website. I don't think the form is the problem since I've implemented that before.
I'm having trouble with getting the users input, hashing the password, and inserting it and all the other data into a table using SQL. I also have conditions (username isn't unique, or if nothing is typed into the fields).
when I run flask run, I would get a 500 error.
here is what I wrote:
register.html:
{% extends "layout.html" %}
{% block title %}
Register
{% endblock %}
{% block main %}
<form action="/register" method="post">
<input type="text" name="email" placeholder="email"><br>
<input type="text" name="username" placeholder="username"><br>
<input type="text" name="password" id="pass" placeholder="password"><br>
<input type="text" name="confirm" id="confirm" placeholde="confirm"><br>
<pre> </pre>
<input type="submit" value= "Submit Form">
</form>
{% endblock %}
application.py:
#app.route("/register", methods=["GET", "POST"])
def register():
"""Register user"""
if request.method == "POST":
#if input isn't typed
if not request.form.get("username"):
return render_template("failuser.html")
if not request.form.get("password"):
return render_template("failpass.html")
if not request.form.get("confirm"):
return render_template("failpass.html")
if request.form.get("password") != request.form.get("confirm"):
return render_template("failpass.html")
#if username already exists
rows = db.execute("SELECT * FROM users WHERE username =: username" ,request.form.get("username"))
if len(rows) >= 1:
return render_template("failuser.html")
#insert info into table
db.execute("INSERT INTO users(username, hash, email) VALUES (:username, :password, :email)",
username = request.form.get("username"),
hash=generate_password_hash(request.form.get("password")),
email=request.form.get("email"))
#remember user
rows = db.execute("SELECT * FROM rows WHERE username = :username",
username=request.form.get("username"))
session["user_id"] = rows[0]["id"]
return render_template("/index")
else:
return render_template("/register")
I think the issue is in the last four lines :
return render_template("/index")
else:
return render_template("/register")
You are trying to return html pages instead you (probably) want to redirect them to that url.
Instead of render_template use redirect

MySQL data is not showing when data entered using HTML form in python

This is the Python code for a flask application :
from flask import Flask, render_template, request
from sqlalchemy import create_engine
import pymysql
db = create_engine("mysql+pymysql://root:password#localhost:3306/database")
app = Flask(__name__)
#app.route("/")
def index():
return render_template("index.html")
#app.route("/success", methods=["POST"])
def success():
name = request.form.get("name")
email = request.form.get("username")
password = request.form.get("password")
rpassword = request.form.get("rpassword")
db.execute("INSERT INTO information(name, email, password, rpassword)
VALUES(name, email, password, rpassword)",
{'name':name, 'email':email, 'password':password,
'rpassword':rpassword})
return render_template("success.html", name=name)
This is the HTML Code
<form id="sign" action="{{url_for('success')}}" method="POST">
Name: <input type="text" name="name"><br><br>
Email: <input type="text" name="username"><br><br>
Password: <input type="password" name="password"><br><br>
Confirm-Password:<input type="password" name="rpassword"><br><br>
<input type="Submit" name="submit" value="Sign Up">
</form>
Whenever I try to add data using HTML form i can enter data successfully and success.html also load but the data is not showing in MySQL
Any suggestion ??
Please read the doc.
https://www.python.org/dev/peps/pep-0249/#paramstyle
Probably for keyword arguments you should use:
"INSERT INTO information(name, email, password, rpassword) VALUES(%(name)s, %(email)s, %(password)s, %(rpassword)s)"
You need to commit when it is DML commands .
https://docs.sqlalchemy.org/en/latest/core/connections.html#using-the-threadlocal-execution-strategy
try:
db.execute(...)
db.commit()
except:
db.rollback()

how to dynamicaly create table column names and insert values using flask and mysql

I would like to create multiple text boxes based on the value given in a particular text box and another text box which will hold table name now I wanted to fetch the table name from the text box and also get the values given in the multiple text boxes as a column name and should create a database in MySQL.
here is my py
from flask import Flask
from flask import request
from flask import render_template
from flaskext.mysql import MySQL
app = Flask(__name__)
mysql = MySQL()
app.config['MYSQL_DATABASE_USER'] = 'root'
app.config['MYSQL_DATABASE_PASSWORD'] = 'root'
app.config['MYSQL_DATABASE_DB'] = 'matrimony'
app.config['MYSQL_DATABASE_HOST'] = 'localhost'
mysql.init_app(app)
#app.route('/')
def index():
return render_template('index1.html')
#app.route('/searchQuery', methods=['POST'])
def search_query():
if request.method: "POST"
conn = mysql.connect()
cursor = conn.cursor()
name=request.form.get('name')
sq_ = request.form.get('searchQuery')
x=request.form.get('x')
cursor.execute("""CREATE TABLE `%s`( NAME VARCHAR(50) DEFAULT NULL) """ % (name))
print(sq_)
return render_template('simplesearch.html', search_query=sq_)
if __name__ == '__main__':
app.run()
index1.html
<form action="{{ url_for('search_query') }}" method="post">
Name:<input type="text" name="name">
Column Number:<input type="text" name="searchQuery" id="searchQuery"><input type="submit" value="Submit">
</form>
simplesearch.html
<table>
{% for x in range(search_query | int) %}
<tr>
<td>
<input type="text" name="i{{ x }}">
<input type="hidden" value="{{ search_query }}">
</td>
</tr>
{% endfor %}
<input type="submit" value="Submit">
</table>
It fetches table name from the tex tbox and only one column is created.
Any help with this would be much grateful Thankyou
I assume you need to create dynamic MySQL tables with user defined fields. You do not need to submit the form twice. Create the dynamic fields using a little help of jQuery. Then handle the values in the controller.
Here is a way you can accomplish this like following. The program requires Flask-MySQL which can be installed using pip install Flask-MySQL.
application.py:
from flask import Flask
from flask import request
from flask import render_template
from flaskext.mysql import MySQL
app = Flask(__name__)
mysql = MySQL()
app.config['MYSQL_DATABASE_USER'] = 'root'
app.config['MYSQL_DATABASE_PASSWORD'] = 'root'
app.config['MYSQL_DATABASE_DB'] = 'matrimony'
app.config['MYSQL_DATABASE_HOST'] = 'localhost'
mysql.init_app(app)
#app.route('/')
def index():
return render_template('index1.html')
#app.route('/create_table', methods=['POST'])
def create_table():
if request.method=="POST":
try:
table_name = request.form.get('table_name')
field_name_list = request.form.getlist('fields[]')
field_list = []
for field in field_name_list:
field_list.append(field+ " VARCHAR(50) DEFAULT NULL")
field_query = " ( " + ", ".join(field_list) + " ) "
create_table_query = 'CREATE TABLE `'+table_name+'`' + field_query
conn = mysql.connect()
cursor = conn.cursor()
cursor.execute(create_table_query)
return "Table: "+table_name+" created successfully"
except Exception as e:
return str(e)
if __name__ == '__main__':
app.run(debug = True)
index1.html:
<form action="{{ url_for('create_table') }}" method="post">
Name:<input type="text" name="table_name" id="table_name" />
Column Number:<input type="text" name="number_of_columns" id="number_of_columns" />
<input type="button" id="generate_field_btn" value="Generate Field" />
<div id="dynamic_field">
</div>
<input type="submit" name="Create Table">
</form>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function(){
$("#generate_field_btn").on("click",function(){
$number_of_columns = $("#number_of_columns").val();
$number_of_columns = parseInt($number_of_columns);
for($i=0; $i<$number_of_columns; $i++){
$field_name = "Field "+($i+1)+": ";
$new_element = $field_name+'<input type="text" name="fields[]"/><br/>';
$("#dynamic_field").append($new_element);
}
})
})
</script>
Output:
Getting input fields from user:
Showing success message after table creation:
Ensure the table is created with desired fields from phpMyAdmin:

Categories