Python/Flask - Display image from file input - python

Plain and simple, I'm aiming to have a user input their name, and select an image from the file input. With some help with my previous question, I was able to get the name to carry over to the next page, but I'm unable to get a selected image to display.
Right now, when filled out, the name and image file name are provided. Hoping to get the image file to actually display the image.
Home page...
Display page...
Here is my current code:
Home.html
{% extends 'base.html' %}
{% block head %}
<title>Home Page</title>
{% endblock %}
{% block body %}
<div class="content-container">
<form action="{{ url_for('result') }}" method="post">
<h2>Input your name:</h2>
<input type="text" class="user-input user mb-3" name="user">
<h2>Select your image:</h2>
<input type="file" accept="image/*" class="form-control-file"
id="formControlFile1" name="image">
<input class="btn btn-outline-primary" type="submit" value="Submit">
</form>
</div>
{% endblock %}
Result.html
{% extends 'base.html' %}
{% block head %}
<title>Result Page</title>
{% endblock %}
{% block body %}
<div class="content-container">
<h2>{{ name }}</h2>
<h2>{{ image }}</h2>
</div>
{% endblock %}
Main.py
from flask import Flask, render_template, request, url_for, redirect
app = Flask(__name__)
#app.route('/', methods=['GET', 'POST'])
def home():
if request.method == 'POST':
user = request.form["user"]
image = request.form["image"]
return redirect(url_for('result', name=user, image=image))
return render_template('home.html')
#app.route("/result", methods=['GET', 'POST'])
def result():
name = request.form.get('user')
image = request.form.get('image')
return render_template("result.html", name=name, image=image)
if __name__ == "__main__":
app.run()
So, yeah, hopefully I explained that easy enough. User inputs name, selects image, and the goal is for the name to show and image to display on the result page. Thanks to anyone that can provide this lowly soul with guidance.

You can try something like that
Your form's enctype should be multipart/form-data
{% extends 'base.html' %}
{% block head %}
<title>Home Page</title>
{% endblock %}
{% block body %}
<div class="content-container">
<form action="{{ url_for('result') }}" method="post" enctype="multipart/form-data">
<h2>Input your name:</h2>
<input type="text" class="user-input user mb-3" name="user">
<h2>Select your image:</h2>
<input type="file" accept="image/*" class="form-control-file"
id="formControlFile1" name="image">
<input class="btn btn-outline-primary" type="submit" value="Submit">
</form>
</div>
{% endblock %}
You need to use request.files and decode in base64
import base64
from flask import Flask, render_template, request, url_for, redirect
app = Flask(__name__)
#app.route('/', methods=['GET', 'POST'])
def home():
if request.method == 'POST':
user = request.form["user"]
image = request.files['image'] # get file
image_b64 = base64.b64encode(image.read()).decode('utf-8')
return redirect(url_for('result', name=user, image_b64=image_b64))
return render_template('home.html')
#app.route("/result", methods=['GET', 'POST'])
def result():
name = request.form.get('user')
image_b64 = request.form.get('image_b64')
return render_template("result.html", name=name, image_b64=image_b64)
if __name__ == "__main__":
app.run()
You should change your HTML to convert image from base64
{% extends 'base.html' %}
{% block head %}
<title>Result Page</title>
{% endblock %}
{% block body %}
<div class="content-container">
<h2>{{ name }}</h2>
<img src="data:image/png;base64, {{ image_b64 }}">
</div>
{% endblock %}

Related

Python Flask, displaying an input from one page on another

None of the other answers on this seem to solve my problem. I am trying to display a greeting that says "Welcome to the app [user]" when someone logs in. I am not sure how to get the greet page to display this message.
Here is my login function
#app.route("/login2", methods=["POST", "GET"])
def login():
if request.method == "POST":
session.permanent = True
user=request.form["nm"]
session["user"] = user
return render_template("greet.html")
else:
if "user" in session:
return redirect(url_for("greet"))
return render_template("login2.html")
Here is my login.html page
{% extends "base.html" %}
{% block title %}Log In Page{% endblock %}
{% block content %}
{% with messages = get_flashed_messages() %}
{% if messages %}
{% for msg in messages %}
<p>{{msg}}</p>
{% endfor %}
{% endif %}
{% endwith %}
<form action="#" method="post">
<p>Name: </p>
<p><input type="text", name="nm" /></p>
<p><input type="submit", value="submit" /></p>
</form>
{% endblock %}
And here is greet.html, which should display the message that I want.
{% extends "base.html" %}
{% block content %} <h1>Welcome</h1>
<p>Hi, Welcome to the app {{}} .</p>
{% endblock %}
I believe that I need to pass something into the {{}} on the greet.html page, but I do not know what to pass in here.
In your login route when the method is POST pass the user object to the template.
#app.route("/login2", methods=["POST", "GET"])
def login():
if request.method == "POST":
session.permanent = True
user=request.form["nm"]
session["user"] = user
return render_template("greet.html", user=user)
else:
if "user" in session:
return redirect(url_for("greet"))
return render_template("login2.html")
Now you can use it in the template
<p>Hi, Welcome to the app {{user.name}} .</p>

Flask - Form Data is None?

I am attempting to setup hard coded authentication just for testing in my def login() route but forms.user_email.data/forms.user_password.data is returning None? I did also notice that form in my def home() is exhibiting the same behavior. I believe this is the root of multiple issues, but I'm honestly not sure. I have read multiple posts about using request - but I've been seeing other people use FlaskForm to achieve this?
Any guidance is greatly appreciated, and any general Flask tips as well - I am quite new to Python/Flask. I have been having a hard time understanding best practices/use-cases for flask/flask_restful, not to mention all the possible extensions like flask_bootstrap, FlaskForm, WTForms, FlaskLogin etc. Thanks in advance.
from flask import Flask, render_template, url_for, redirect, flash
from flask_restful import Resource, Api
from flask_wtf import FlaskForm
import requests
import pandas as pd
from flask_bootstrap import Bootstrap
from wtforms import EmailField, PasswordField, StringField
from wtforms import validators
app = Flask(__name__)
api = Api(app)
app.config['SECRET_KEY'] = 'd43b80c0727dca296c607fe8f8db478264'
bootstrap = Bootstrap(app)
class LoginForm(FlaskForm):
user_email = EmailField('Email', validators=[validators.DataRequired()])
user_password = PasswordField('Password', validators=[validators.DataRequired()])
class InputForm(FlaskForm):
ticker = StringField('Ticker', validators=[validators.DataRequired()])
class GetStonks(Resource):
def get(self, ticker):
HEADER = {"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:91.0) Gecko/20100101 Firefox/91.0"}
try:
response = requests.get(f"https://finviz.com/quote.ashx?t={ticker}", headers=HEADER)
result = pd.read_html(response.text)
parsed = result[5]
dict_primary = {}
dict_primary |= dict(parsed[[0,1]].values)
dict_primary |= dict(parsed[[2,3]].values)
dict_primary |= dict(parsed[[4,5]].values)
dict_primary |= dict(parsed[[6,7]].values)
dict_primary |= dict(parsed[[8,9]].values)
dict_primary |= dict(parsed[[10,11]].values)
return dict_primary, 200
except IndexError:
return {"Message": "Ticker ID not found."}
api.add_resource(GetStonks, "/api/v1/stocks/<string:ticker>")
#app.route('/')
#app.route("/login", methods=['GET', 'POST'])
def login():
form = LoginForm()
if form.validate_on_submit():
if form.user_email.data == 'admin#admin.com' and form.user_password.data == 'admin':
return redirect(url_for('home'))
else:
flash('Authentication failure', 'danger')
return render_template('login.html', title='Login', form=form)
#app.route("/home", methods=['GET', 'POST'])
def home():
form = InputForm()
return render_template('home.html', title='Home', form=form)
if __name__ == '__main__':
app.run(debug=True)
home.html
{% extends "bootstrap/base.html" %}
{% import "bootstrap/wtf.html" as wtf %}
{% import "bootstrap/utils.html" as utils %}
{% block title %}
Home
{% endblock %}
{{super()}}
<link rel="stylesheet" href="{{url_for('.static', filename='signin.css')}}">
{% block body %}
<div class="container">
<form class="form-signin" method="POST" action="http://127.0.0.1:5000/api/v1/stocks/{{url}}">
<h2 class="form-signin-heading">INPUT TICKER BELOW</h2>
<br>
{{ form.hidden_tag() }}
{{ form.csrf_token }}
{{ wtf.form_field(form.ticker) }}
<button class="btn btn-lg btn-primary" type="submit">GET</button>
</form>
</div>
{% endblock %}
login.html
{% extends "bootstrap/base.html" %}
{% import "bootstrap/wtf.html" as wtf %}
{% import "bootstrap/utils.html" as utils %}
{% block title %}
Login
{% endblock %}
{{super()}}
<link rel="stylesheet" href="{{url_for('.static', filename='signin.css')}}">
{% block content %}
<div class="container">
<form class="form-signin" method="POST" action="{{ url_for('home') }}">
<h2 class="form-signin-heading">SIMPLE STOCK API</h2>
<br>
<br>
{{ form.hidden_tag() }}
{{ form.csrf_token }}
{{ wtf.form_field(form.user_email) }}
{{ wtf.form_field(form.user_password) }}
<button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
</form>
</div>
{% endblock %}
Inside your login.html instead of:
<form class="form-signin" method="POST" action="{{ url_for('home') }}">
Action should be login instead of home. So it should look like this:
<form class="form-signin" method="POST" action="{{ url_for('login') }}">

Accessing image from Cloud Storage

I'm pretty new to python and Google Cloud. I'm developing a website that needs to retrieve image from Cloud Storage and serve it to HTML. I deploy my Flask on App Engine and the image is can't be served it.
My Flask code looks like this:
#app.route('/translate')
def translate():
return render_template("translate.html")
#app.route('/get-image', methods=['GET', 'POST'])
def get_image():
if request.method == 'POST':
name = request.form.get("huruf")
filepath = name + ".png"
buc = storage_client.get_bucket(CLOUD_STORAGE_BUCKET)
blob = buc.blob(filepath)
filename = blob.download_to_filename(filepath)
return render_template("get-translate.html", nama=name, pict=filename)
else:
return redirect(url_for(translate))
Here is my HTML that input request:
{% extends "base.html" %}
{% block title %} Get Image - Isyaratku {% endblock %}
{% block content %}
<br>
<form action="/get-image" method="post">
<label for="huruf">Huruf :</label>
<input type="text" name="huruf">
<br>
<input type="submit" value="SUBMIT">
</form>
{% endblock %}
And here is my HTML for a received image from Cloud Storage:
{% extends "base.html" %}
{% block title %} Get Translate - Isyaratku {% endblock %}
{% block content %}
<h1>{{ nama }}</h1>
<img src="{{ pict }}" alt="gmb">
{% endblock %}

How can I add 2 working forms to the same template?

I need to add 2 separate forms to the same web page and I cannot get the second form to output any information.
In my research I saw people suggesting to split the forms onto 2 different def functions but I am having trouble figuring out how to do that an keep both forms usable at the sane time.
from flask import Flask, session, render_template, url_for, redirect
from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField
app = Flask(__name__)
app.config['SECRET_KEY'] = 'b317a06ad972917a84be4c6c14c64882'
class PostForm(FlaskForm):
content = StringField('Content')
submit = SubmitField('Submit')
class SecondPostForm(FlaskForm):
content = StringField('Second Content')
submit = SubmitField('Second Submit')
#app.route("/", methods=['GET', 'POST'])
#app.route("/home", methods=['GET', 'POST'])
def home():
form = PostForm()
second_form = SecondPostForm()
if form.validate_on_submit():
print(form.content.data)
session['content'] = form.content.data
redirect(url_for('submit'))
return redirect(url_for('submit'))
'''
--------------------------------------------------------------------
is it possible to split the second if statement onto its own def and keep
them both usable on the same page at the same time?
--------------------------------------------------------------------
'''
elif second_form.validate_on_submit():
print(second_form.content.data)
session['content'] = second_form.content.data
return redirect(url_for('othersubmit'))
return render_template('example.html', second_form=second_form, form=form)
#app.route("/submit", methods=['GET', 'POST'])
def submit():
content = session.get('content', None)
print(content)
session.pop('content', None)
return redirect(url_for('home'))
#app.route("/othersubmit", methods=['GET', 'POST'])
def othersubmit():
print('othersubmit')
content = session.get('content', None)
print(content)
session.pop('content', None)
return redirect(url_for('home'))
if __name__ == "__main__":
app.run(debug=True)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div class="content-section">
<form method="POST" action="">
{{ form.hidden_tag() }}
<fieldset class="form-group">
<legend class="border-bottom mb-4">{{ legend }}</legend>
<div class="form-group">
{{ form.content.label(class="form-control-label") }}
{% if form.content.errors %}
{{ form.content(class="form-control form-control-lg is-invalid") }}
<div class="invalid-feedback">
{% for error in form.content.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.content(class="form-control form-control-lg") }}
{% endif %}
</div>
</fieldset>
<div class="form-group">
{{ form.submit(class="btn btn-outline-info") }}
</div>
</form>
<form method="POST" action="{{ url_for('othersubmit') }}">
{{ second_form.hidden_tag() }}
<fieldset class="form-group">
<legend class="border-bottom mb-4">{{ legend }}</legend>
<div class="form-group">
{{ second_form.content.label(class="form-control-label") }}
{% if second_form.content.errors %}
{{ second_form.content(class="form-control form-control-lg is-invalid") }}
<div class="invalid-feedback">
{% for error in second_form.content.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ second_form.content(class="form-control form-control-lg") }}
{% endif %}
</div>
</fieldset>
<div class="form-group">
{{ second_form.submit(class="btn btn-outline-info") }}
</div>
</form>
</div>
</body>
</html>
I have tried with and without action="{{ url_for('othersubmit') }}" neither have the desired result
The goal is to have either form print its own data and also print which form it came from. At the moment the 1st form prints the same data twice and the 2nd form doesn't print anything.
You can do few things:
1) Firstly, if you have 2 forms on one page, you can't have two {{ second_form.hidden_tag() }}, as they will throw error of having same id. As per wtform documentation, I have handled it as {{ form.csrf_token(id='login_csrf') }}. See you can specify your own id, so this will prevent clash.
2) Change the Submit button name in both the forms. So that they are distinct. Then you can do as below. As you can see i have 2 forms on same page form_login and form_reg. I have kept submit buttons name differet. One is login and another is register.
if form_login.login.data:
if form_login.validate_on_submit():
#do something here
elif form_reg.register.data:
if form_reg.validate_on_submit():
#do something here
return render_template('abc.html')
This should work for you.

Getting user input using django forms.py return nothing

I'm trying to get the users input and add to a table in the database, everything goes smoothly with no errors .. but the input is not added to DB
urls.py
path('category/add/', views.add_cat, name="add_cat"),
view.py
def add_cat(request):
# if this is a POST request we need to process the form data
if request.method == 'POST':
# create a form instance and populate it with data from the request:
form = CatForm(request.POST)
# check whether it's valid:
if form.is_valid():
# process the data in form.cleaned_data as required
entry = Categories.objects.create(category_name=new_cat_name)
entry.save()
# ...
# redirect to a new URL:
return HttpResponseRedirect('/')
# if a GET (or any other method) we'll create a blank form
else:
form = CatForm()
return render(request, 'add_cat.html', {'form': form})
add_cat.html
{% extends 'base.html' %}
{% block content %}
{% load static %}
<form action="/" method="post">
{% csrf_token %}
{% for form in form %}
<h3 align="center">{{ form.label }}</h3>
<div align="center">{{ form }}</div>
<br>
<br>
{% endfor %}
<div align="center">
<input type="submit" class="btn btn-dark" style="width: 100px;"value="إضافة" />
</div>
</form>
{% endblock %}
{% extends 'base.html' %}
{% block content %}
{% load static %}
<form action="" method="post">
{% csrf_token %}
{% for form in form %}
<h3 align="center">{{ form.label }}</h3>
<div align="center">{{ form }}</div>
<br>
<br>
{% endfor %}
<div align="center">
<input type="submit" class="btn btn-dark" style="width: 100px;"value="إضافة" />
</div>
</form>
{% endblock %}
change your form action, you were posting the data to '/' url but you need to put it in your add view
if form.is_valid():
form.save()
return HttpResponseRedirect('/')

Categories

Resources