Get value from URL in another app.route - python

I have a Flask application that shows text under the URL http://<webroot>/idea/<idea_id>, e.g. http://localhost/idea/123. The idea_id is requested from a database
#app.route("/idea/<idea_id>", methods=["POST","GET"])
def get_idea(idea_id):
db = get_db()
cur = db.execute("select id, title, description, image from ideas where id=?", (idea_id,))
ideas = cur.fetchall()
args = request.path
return render_template("idea.html", ideas=ideas)
In that page I got a file upload:
<form action="{{ url_for("upload_image") }}" method="post" enctype="multipart/form-data">
<p><input type="file" name="image">
<input type=submit value="Hochladen">
</form>
Here's the code that does the upload:
#app.route("/upload_image", methods=["POST", "GET"])
def upload_image():
if not session.get("logged_in"):
abort(401)
image = request.files["image"]
if image and allowed_file(image.filename):
db = get_db()
idea_id = request.view_args["idea_id"]
filename = secure_filename(image.filename)
db.execute("INSERT OR REPLACE INTO ideas (id, image) VALUES (?, ?)", (idea_id, filename))
image.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
return flash("Bild hochgeladen!")
return redirect(url_for("index"))
I want to insert the path of the image into the database and link it to the ID of the idea (idea_id).
My question is how to get the idea_id-value from used in the URL? I guess I need to URL processors, but I can't wrap my head around the whole process yet.

I would do it as a hidden input in your form.
<form action="{{ url_for("upload_image") }}" method="post" enctype="multipart/form-data">
<input type="hidden" name="idea_id" value="{{ idea_id }}">
<p><input type="file" name="image">
<input type=submit value="Hochladen">
</form>
This would also require modifying your view.
#app.route("/idea/<idea_id>", methods=["POST","GET"])
def get_idea(idea_id):
db = get_db()
cur = db.execute("select id, title, description, image from ideas where id=?", (idea_id,))
ideas = cur.fetchall()
args = request.path
return render_template("idea.html", ideas=ideas, idea_id=idea_id)
This would put idea_id into request.form. You can then access it from upload_image with request.form['idea_id'].

Related

Redirection in flask adds a question mark, why? [duplicate]

Here's my code:
{% if request.path == '/employees' %}
<form action="{{ url_for('employees_name', employee_id=x) }}" />
EmployeeId: <input type="text" name=x><br>
<input type="submit" value="Submit">
</form>
{% endif %}
E.g. when I input "1" as an output I get:
http://127.0.0.1:5002/employees/?x=1
but I need this:
http://127.0.0.1:5002/employees/1
Here's my Python code:
app = Flask(__name__)
api = Api(app)
class Employees_Name(Resource):
def get(self, employee_id):
conn = db_connect.connect()
query = conn.execute("select * from employees where EmployeeId =%d " %int(employee_id))
result = {'data': [dict(zip(tuple (query.keys()) ,i)) for i in query.cursor]}
return Response(render_template('test.html', result=result, mimetype='text/html'))
api.add_resource(Employees, '/employees')
Is there a way to do it? Thanks
When using 'GET' to handle form, the form data will be formatted as a query string appended after URL. The normal way is to use a POST endpoint to handle form and validate form data, then redirect to a GET endpoint like yours.
So, the code may like this:
from flask import request, url_for, redirect
...
class Employees(Resource):
def post(self):
employee_id = request.form.get('employee_id')
# validate...
return redirect(url_for('employee', employee_id=employhee_id))
class Employee(Resource):
def get(self, employee_id):
conn = db_connect.connect()
...
api.add_resource(Employees, '/employees')
api.add_resource(Employee, '/employees/<int:employee_id>') # this rule is waht you want
In the template:
<form action="{{ url_for('employees') }}">
EmployeeId: <input type="text" name="employee_id"><br>
<input type="submit" value="Submit">
</form>

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.

html form - get rid of question mark and equation

Here's my code:
{% if request.path == '/employees' %}
<form action="{{ url_for('employees_name', employee_id=x) }}" />
EmployeeId: <input type="text" name=x><br>
<input type="submit" value="Submit">
</form>
{% endif %}
E.g. when I input "1" as an output I get:
http://127.0.0.1:5002/employees/?x=1
but I need this:
http://127.0.0.1:5002/employees/1
Here's my Python code:
app = Flask(__name__)
api = Api(app)
class Employees_Name(Resource):
def get(self, employee_id):
conn = db_connect.connect()
query = conn.execute("select * from employees where EmployeeId =%d " %int(employee_id))
result = {'data': [dict(zip(tuple (query.keys()) ,i)) for i in query.cursor]}
return Response(render_template('test.html', result=result, mimetype='text/html'))
api.add_resource(Employees, '/employees')
Is there a way to do it? Thanks
When using 'GET' to handle form, the form data will be formatted as a query string appended after URL. The normal way is to use a POST endpoint to handle form and validate form data, then redirect to a GET endpoint like yours.
So, the code may like this:
from flask import request, url_for, redirect
...
class Employees(Resource):
def post(self):
employee_id = request.form.get('employee_id')
# validate...
return redirect(url_for('employee', employee_id=employhee_id))
class Employee(Resource):
def get(self, employee_id):
conn = db_connect.connect()
...
api.add_resource(Employees, '/employees')
api.add_resource(Employee, '/employees/<int:employee_id>') # this rule is waht you want
In the template:
<form action="{{ url_for('employees') }}">
EmployeeId: <input type="text" name="employee_id"><br>
<input type="submit" value="Submit">
</form>

Flask: redirect to same page after form submission

I have two forms on in my template: one, to post something and the second, to activate file deletion on the server:
<div style="margin-bottom:150px;">
<h4>Delete</h4>
<form method="post" action="/delete">
<div class="form-group">
<input type="hidden" name="delete_input"></input>
</div>
<button type="submit" class="btn btn-danger" id="btnSignUp">Delete</button>
</form>
</div>
<div style="margin-bottom:150px;">
<h4>URLs</h4>
<form method="post" action="/">
<div class="form-group">
<textarea class="form-control" rows="5" id="urls" name="url_area"></textarea>
</div>
<button type="submit" class="btn btn-primary" id="btnSignUp">Urls</button>
</form>
</div>
My app.py looks like this:
#app.route("/")
def main():
return render_template('index.html')
#app.route('/', methods=['POST'])
def parse_urls():
_urls = request.form['url_area'].split("\n")
image_list = get_images(_urls)
return render_template('index.html', images=image_list)
#app.route('/delete', methods=['POST'])
def delete_images():
file_list = [f for f in os.listdir("./static") if f.endswith(".png")]
for f in file_list:
os.remove("./static/" + f)
image_list = []
conn = sqlite3.connect('_db/database.db')
curs = conn.cursor()
sql = "DROP TABLE IF EXISTS images"
curs.execute(sql)
conn.commit()
conn.close()
return render_template('index.html', images=image_list)
Two issues:
I get the form resubmission message when I reload the page after submitting the form
I would like to have one url for everything
The way I see it, I need so use redirects to avoid the duplicate submission and after calling delete, I need to redirect to index.
How can I do this correctly?
I know about redirect and url_for, but how do I redirect to the same page?
You can get the currently requested URL by request.url:
So, to redirect to the same page use:
redirect(request.url)
This worked perfectly for me, in last line:
return redirect(request.referrer)
Change form action to action="{{url_for('delete_images')}}". And for redirection you can use code below:
#app.route('/delete', methods=['POST'])
def delete_images():
return redirect(url_for('delete_images'))
As archer said below:
return redirect(request.referrer)
This is useful when you have a button that uses a route to perform a given function when it is clicked - you don't want to return the user to the URL for that button - you want to return the user to the URL that the button route was referred by, i.e. the page the user was on when they clicked the button.
However, as Mahmoud said:
redirect(request.url)
This is perfect if you perform a function on a page that doesn't use routes or special URLs or anything like that. It essentially just refreshes the page.
One way is set the current url by Javascript in your form. like:
<form method="post" action="/delete">
<div class="form-group">
<input type="hidden" name="delete_input"></input>
</div>
<input type=hidden class=current_url value="" name=current_url>
<button type="submit" class="btn btn-danger" id="btnSignUp">Delete</button>
</form>
And set the hidden input value by JS, like,
function get_current_url() {
var url=window.location.href;
return url
}
$(window).on('load',function(){
var current_url=document.getElementsByClassName('current_url')[0];
current_url.value=get_current_url();
})
At server, redirect to the url that post data

Categories