HTML form data not updating in postgres Table throug flask python - 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

Related

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

how can i display mysql content using 2 for loops is flask jinja2

I have written a code in flask in which users are allowed to upload images and along with image they can ask questions
for taking user questions i have created a form and on submitting form user questions are stored into the database
I am able to retrieve the question from database and images and diplay them in HTML using jinja2
What I want is to display the image and below that display its comment
from flask import Flask,request,render_template,redirect,url_for,session,logging,flash,send_from_directory
from flask_sqlalchemy import SQLAlchemy
import pymysql
pymysql.install_as_MySQLdb()
from flask_mail import Mail
app = Flask(__name__)
import os
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:#localhost/akashauto'
db = SQLAlchemy(app)
class Upload_tb(db.Model):
snob = db.Column(db.Integer, primary_key=True)
commentb = db.Column(db.String(20), unique=True, nullable=False)
datab = db.Column(db.String(20), unique=True, nullable=False)
APP_ROOT=os.path.dirname(os.path.abspath(__file__))
#app.route("/plcpro")
def problem():
return render_template("plcpro.html")
#app.route("/uploader",methods=["GET","POST"])
def uploader():
target=os.path.join(APP_ROOT,"images/")
print(target)
if not os.path.isdir(target): #if folder does not exist . create a folder
os.mkdir(target)
if(request.method=='POST'):
f=request.files['file1']
text=request.form.get('comment')
filename=f.filename
f.save(os.path.join(target,filename))
image=os.listdir('./images')
existing_entry=Upload_tb.query.filter_by(commentb=text).first()
if existing_entry:
# flash('Email already exist','danger')
return redirect(url_for("plcove"))
new_entry=Upload_tb(commentb=text,datab=filename)
db.session.add(new_entry)
db.session.commit()
question=Upload_tb.query.all()
return render_template('ans.html',file=filename,text=text,image=image,question=question)
#app.route("/uploader/<filename>")
def send_img(filename):
return send_from_directory("images",filename)
This is the Form code
<form id="upload-form" action="/uploader" method="POST" enctype="multipart/form-data" onsubmit=" return askvalidateform()">
<div class="form-group">
<label for="name">Enter Name:</label>
<input type="text" class="form-control" id="name" name="name" placeholder="Enter your name">
<span id="nameerror" class="text-danger"></span>
</div>
<div class="form-group">
<label for="comment">Ask Your Question: </label>
<textarea rows="5" cols="30" class="form-control " id="comment" name="comment"
placeholder="Ask Question"></textarea>
<span id="commenterror" class="text-danger"></span>
</div>
<input type="file" name="file1" accept="image/" multiple>
<input type="submit" value="send">
</form>
display code
{% for image_name in image %}
<li class="list"><img src="{{url_for('send_img',filename=image_name)}}"></li>
{%endfor%}
<p class="para">{% for user in question %}</p>
<li class="list">Comment - {{user.commentb}}</li>
{% endfor %}
The output i am getting is
enter image description here
1st images are displayed and then comments what i want to display is image and its comment together so can i do some changes in for loop?Any help will be appriciated
You could use this method
Iterate through both the array and the access the values.
{% for i in range(image|lenght)%}
<p> {{question[i].commentb }} </p>
<img src='url_for("send_image",filename=images[i])}}'>
{% endfor %}

Cannot insert row using Flask and SQLAlchemy

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})

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:

Using Flask to send form data to a database

I've created a simple web page with a text field and a button. I want my application to update a record in my database with the content of the text field when I click the button. Seems simple enough, but I can't figure out what I'm missing. Here's my code thus far:
app.py sample
#app.route('/update-audit/', methods=['POST'])
def update_audit(test_name, description):
cur = connect_db()
cur.execute('UPDATE audit SET description = ? WHERE test_name = ?', (description, test_name,))
return render_template('clicked.html')
audit.html sample
<form action="{{ url_for('update_audit') }}" method="post">
<td>{{ row[2] }}</td>
<td>
<input type="text" id="desc" value="{{ row[3] }}" size="140">
<input type="hidden" name="update_audit" value="{{ row[2] }}, desc"/>
<input type="submit" class="btn btn-success" value="Update"/>
</td>
</form>
clicked.html
<!DOCTYPE html>
{% extends "layout.html" %}
{% block content %}
<body>
{{ form.description }}<br />
</body>
{% endblock %}
table sample
id | tool name | test name | description
========================================
1 | "tool1" | "test1" | "update me!"
Not sure if I'm missing an essential concept (I played around with flask_wtf and didn't get anywhere) or if I'm a step or two away from making this happen.
Set a name attribute for text input so that it gets sent with the submitted form.
<input name="description" type="text" id="desc" value="{{ row[3] }}" size="140">
Update your view function to get description from the POST dictionary attribute of request. test_name also needs to be updated to an appropriate value.
#app.route('/update-audit/', methods=['POST'])
def update_audit():
description = request.form.get('description')
test_name = request.form.get('update_audit')
cur = connect_db()
with cur:
cur.execute(
'UPDATE audit SET description = ? '
'WHERE test_name = ?;', (description, test_name,))
# commit changes to the database
return render_template('clicked.html')
Figured it out:
app.py sample
#app.route('/update-audit/', methods=['POST'])
def update_audit():
description = request.form.get('description')
test_name = request.form.get('test_name')
sql = 'UPDATE audit SET description=? WHERE test_name=?'
conn = sqlite3.connect(DATABASE)
cur = conn.cursor()
cur.execute(sql, (description, test_name))
conn.commit()
conn.close()
return render_template('clicked.html', data=(test_name, description))
audit.html sample
<form action="{{ url_for('update_audit') }}" method="POST">
<td>
<input type="hidden" name="test_name" value="{{ row[2] }}">{{ row[2] }}</input>
</td>
<td>
<input type="text" name="description" id="desc" value="{{ row[3] }}" size="100" maxlength="140"/>
<input type="submit" class="btn btn-success" value="Update"/>
</td>
</form>
</tr>
The answer is a combination of the right SQL-Alchemy commands, and ensuring that I'm sending the data to the update_audit function via two input-tags in audit.html.
Your render_template should get a form argument:
return render_template('clicked.html', form=form)
It is also not clear in the code you provided where the Forms are treated in python and where the variable row comes from.

Categories