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?
Related
So after submitting a form, the action is to run a function to validate the input using wtforms, however the error message that i've set did not show up and the whole page went to a TypeError where there is not a return statement which I understand why, but I want to show the error message
So this is the Flask function:
#app.route('/createTodo', methods=['POST', 'GET'])
def a_create_todo():
create_todo_form = CreateTodo(request.form)
if request.method == 'POST' and create_todo_form.validate():
todo_dict = {}
db = shelve.open('todo.db', 'c')
try:
todo_dict = db['Todo']
Todo.count_id = db['Todo_id']
except:
print("Error in retrieving To Do list from Database")
date = datetime.now()
date = date.strftime("%A, %d %B %Y %I:%M%p")
todo = Todo(create_todo_form.text.data, date)
todo_dict[todo.get_todo_id()] = todo
db['Todo'] = todo_dict
db['Todo_id'] = Todo.count_id
db.close()
return redirect(url_for('admin_main'))
HTML:
<form action="{{url_for('a_create_todo')}}" method="POST">
<div class="d-flex">
<input
class="form-control"
id="text"
name="text"
type="text"
value=""
pattern="^(?!\s*$).+"
/>
<button type="submit" class="btn add-button">
<i class="bi bi-plus-circle-fill add-button ps-2"></i>
</button>
</div>
</form>
WTForms python file:
class CreateTodo(Form):
text = StringField('', validators=[
Regexp(regex="^(?!\s*$).+", message="This is a required field")
])
I am expecting an error message but the page went to a TypeError
if you just want to display the validation error in the backend you can just print form.errors like the docs say http://wtforms.simplecodes.com/docs/0.6.2/forms.html#wtforms.form.Form.errors
Also if you want to show the validation error on the html page i think you need to call the form on the template like {{ form.text.errors }}
Note: This other stackoverflow question can help you how to view WTForms validation errors?
I have created an html form in add_appointment.html and have created database "hospital", table "appointment" in MySQL. I able to view values that I inserted into my database on another html page called view_appointment.html but I do not know how to take html form input from the "add_appointment.html" file and insert it into MySQL database.
I searched for a solution everywhere, but I don't see people doing it in python Django, its just php everywhere and python but with flask, if you can help with some link I'll be grateful.
(I'm a beginner, in college, doing a project for the first time. I figured it out somehow until now but got stuck here. My project is almost done except this one thing, I promise if someone helps me the day I become good enough I'll try my best to help others as well )
filename: add_appointment.html
<!doctype html>
<html lang="en">
<head><title>Add Appointment</title></head>
<body>
<div class="container">
<form id="form" class="form">
<div class="from-control">
<h1> Add Appointment</h1>
<div class="form-control">
<label for="username">Name</label>
<input type="text" id="name" placeholder="Enter name">
<small>Error Message</small>
</div>
<div class="form-control">
<label for="email">Email</label>
<input type="text" id="email" placeholder="Enter email">
<small>Error Message</small>
</div>
<div class="form-control">
<label for="id">ID</label>
<input type="text" id="id" placeholder="Enter ID">
<small>Error Message</small>
</div>
<div class="form-control">
<label for="category">Disease</label>
<input type="text" id="category" placeholder=" disease">
<small>Error Message</small>
</div>
<button>Add</button>
</form>
</div>
<center>View Appointments</center>
</body>
</html>
filename: appointment.py
import mysql.connector
import webbrowser
conn = mysql.connector.connect(user='root', password='Newtonlaw3', host='localhost', database='hospital')
if conn:
print("connected successfully")
else:
print("connection not established")
select_admin = """SELECT * FROM appointment"""
cursor = conn.cursor()
cursor.execute(select_admin)
result = cursor.fetchall()
p = []
tbl = "<tr><td><NAME</td><td>EMAIL</td><td>ID<td>SPECIALITY</td></tr>"
p.append(tbl)
for row in result:
a = "<tr><td>%s</td>" % row[0]
p.append(a)
b = "<td>%s</td>" % row[1]
p.append(b)
c = "<td>%d</td>" % row[2]
p.append(c)
d = "<td>%s</td></tr>" % row[3]
p.append(d)
contents = '''<!DOC TYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta content ="text/html; charset=ISO-8859-1"
http-equiv = "content-type">
<title> View Appointments</title>
</head>
<body>
<table>
%s
</table>
</body>
</html>
''' % (p)
filename = 'view_appointment.html'
def main(contents, filename):
output = open(filename, 'w')
output.write(contents)
output.close()
main(contents, filename)
webbrowser.open(filename)
if (conn.is_connected()):
cursor.close()
conn.close()
print("my sql connection is closed")
what you need is a <form method="POST"> ... </form> that surrounds all <input> fields.
Inside that form you also need a <button class="btn" type="submit">Submit</button> so that the data your user enters is sent to the function that renders this html.
This function could look something like this (in views.py):
def add_appointment(request):
if request.method == 'POST':
# retrieve data from input fields
# save data to MySQL
return redirect('view_appointment')
return render(request, 'add_appointment')
If the appointment always has the same attributes, it also would be easier to look into Models and ModelForms.
I'll take a shot at answering this, although I'm by no means a pro.
It seems like you might be misunderstanding how Django works. From my understanding, Django is going to be interacting with your database for you. Django's models allow you to specify what format you want your data in, and based on that, will create tables in SQL for you. Check out Writing your first Django app part 2 . It has an example of models being defined, and what SQL django generates for those models.
So in your situation, you need 3 things:
A model, specifying what data you want to include in your database, for example:
models.py
class AppointmentInformation(models.Model):
username = models.CharField()
email = models.EmailField()
# etc etc
A form. You can let Django automatically generate this from the model, or if you'd rather not do that, you can specify the form manually. If you'd like to specify manually, take a look at this post regarding saving Django form data without using ModelForm. In any case, you need to specify how you want the form to display in forms.py. I would suggest looking through the Django form building documentation for this. In your HTML you're currently missing an action (where the browser will return the form data, this will usually be the view that you've written to handle the POST data), and a method (if you're submitting data, this will be post), e.g:
<form action="." method="post">
<!-- form stuff -->
<input type="submit" value="OK">
</form>
A view. This tells Django what you want to do with the form data, and where the form data will be saved. For example:
views.py
def create_appointment(request):
if request.method == 'POST':
# Whatever you named your form in forms.py
form = ExampleForm(request.POST)
if form.is_valid():
# Whatever you named your model.
obj = ExampleModel()
# If you used model form, you can use obj.save(). If you
# manually specified your form, you'll have to follow the example
# in the link above regarding saving data without model form
else:
# If request.method == "GET", render form to be filled in webpage.
form = ExampleForm()
return render(request, 'add_appointment.html', {'form':form})
In the above view, the obj.save() function will save the data from your form in the database.
If you're new to Django, I'd really recommend completing the tutorial on their website, and then completing it a second time, it will cement the workflow much better for you.
I have created a web app on pythonanywhere, in which I have displayed a dynamic table using flask (jinja2 templating). However, I am not able to update the table by clicking checkboxes.
the table
If I want to filter this table (let's say I want to display only Turnips and Peas), nothing happens. If I run the program on my localhost, it works completely fine and updates the table after checking the boxes and sending the form. I know I have to update my app.py to somehow re-route the page, but I am not able to figure it out for this particular application. I have tried numerous things using requests and different routes, without success so far.
My HTML template code:
<!-- create checkboxes to let the users chose the crop type -->
<form action="" method="get">
<input type="checkbox" name="field" value="PEAS">Peas</input>
<input type="checkbox" name="field" value="OIL">Oil Seed Rape</input>
<input type="checkbox" name="field" value="POTATO">Potatoes</input>
<input type="checkbox" name="field" value="STRAW">Strawberries</input>
<input type="checkbox" name="field" value="TURNIPS">Turnips</input>
<input class="smallButton" type="submit" value="Go!">
</table>
and my app.py:
app = Flask(__name__)
#app.route("/", methods=["GET", "POST"])
def print_html():
inpFields = fieldsHtml()
return render_template('fieldsTemp.html', fields=inpFields)
...
...
# get the form entry from "fields.html" and assign the elements to a list, then to a string and add it to the SQL statement
form = cgi.FieldStorage()
field = form.getlist('field')
input = "%' OR CROPS.NAME LIKE '%".join(field)
conn = mysql.connector.connect(
host= "xxxx.mysql.pythonanywhere-services.com", user="xxxx", password="xxxx", db="xxxx$fieldsFinds")
c = conn.cursor()
# c.execute("USE fieldsFinds")
c.execute(
f"SELECT * FROM FIELDS JOIN CROPS ON FIELDS.CROP = CROPS.CROP WHERE CROPS.NAME LIKE '%{input}%'")
Note that the second part of the code is within the fieldsHtml() function, which I assign to the render_template.
Many thanks in advance for any inputs.
You have a return statement as the second line in print_html, so nothing after that is executed.
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})
I've got problem with updating data in html table in index.html after I enter them in add.thml
I have homepage where is only table
{% block body %}
<h1>Project</h1>
{{ table }}
{% endblock %}
which is made with flask_table library - it just puts data from SQLite database into html table.
items = Package.select(Package)
table = ItemTable(items)
def populate_table(table):
items = Package.select(Package)
table = ItemTable(items)
return table
I get data from this html form from subpage named add
<form action=" {{ url_for('save') }}" method="POST">
Name: <input type="text" name="name">
<br>
Dimensions: <input type="text" name="dimensions">
<br>
Weight: <input type="text" name="weight">
<br>
Status: <input type="text" name="status">
<input type="submit" name="my-form" value="Submit">
</form>
Then after clicking on submit I run save
#fproject.route('/save', methods=['POST'])
def save():
text.append(request.form['name'])
text.append(request.form['dimensions'])
text.append(request.form['weight'])
text.append(request.form['status'])
add_package.add_package_values(text)
add_package.add_package_to_db(new_package)
populate_table(table)
del text[3]
del text[2]
del text[1]
del text[0]
return redirect(url_for('index'))
it saves values entered by user to database. Then it redirects to homepage (index.html):
#fproject.route('/')
def index():
context={'table': table}
return render_template("index.html", **context)
The problem is, that when I come back to index.html I can't see data I enetered in add.html They are in database, but they don't appear in the table. When I restart the app, they are there. But I need them to be there immediately. I tried to put render_template("index.html") into save function, but it still doesn't work. I somehow need html table to be updated or index.html to be rendered again (it will get data from db again - as well the new record I entered at add.html)
How to do that guys ? Thanks
In your save function you are not storing any data in the global table variable. Modify this function like this:
#fproject.route('/save', methods=['POST'])
def save():
global table
text.append(request.form['name'])
text.append(request.form['dimensions'])
text.append(request.form['weight'])
text.append(request.form['status'])
add_package.add_package_values(text)
add_package.add_package_to_db(new_package)
table = populate_table(table)
return redirect(url_for('index'))
I added global table and your populate_table function has a return value, so use it.