Send data to html page through python - python

I have a python-flask app. And my source.py :
from flask import Flask, flash, redirect, render_template, request, session, abort
import os
from Modules.registry_bend.DockerImageReceiver import http_requester_v2_catalog, read_configurations
app = Flask(__name__)
#app.route('/v1')
def display_index():
return render_template('index.html')
if __name__ == "__main__":
# http_requester_v2_catalog("192.168.1.7", 5000)
app.secret_key = os.urandom(12)
app.run(debug=True, host='0.0.0.0', port=3150)
I run this source.py, and then open the browser and hit localhost:5000/v1.Then index.html appears. So, the challenge is, that a few seconds later I get some data, and I want to add them to index.html. How could it be possible? I have already called index.html once.

You can send the dynamic data to your HTML by sending context variables through the render template method.
flask.render_template(template_name_or_list, **context)
Renders a template from the template folder with the given context.
Parameters:
template_name_or_list – the name of the template to be rendered, or an iterable with template names the first one existing will be rendered
context – the variables that should be available in the context of the template.
Example -
return render_template('index.html', variable1=random.random(), variable2=random.random())
And in your HTML code you need to include these flask variables.
Example -
<p> {{variable1}} </p>
<p> {{variable2}} </p>
And whenever you refresh you html page in your browser. The new data will be displayed.

Related

Flask background processing after render template

I'm trying to submit a form, where the user can potentially upload several files, from which a background process is triggered that will take several minutes to complete. The issue I have currently is that when the user clicks the Submit button, nothing appears to happen for the user for several seconds while the files upload. Is there a way I can redirect to a (static*) holding page while the files upload and the processing happens, and then once the background process completes, this renders a new template?
Using Python 3.6.1 and Flask 0.12.2.
* I say static for now, but at some point in the future, I wish to use AJAX to update this page to give more information to the user
N.B. I have seen several similar questions, and the general answer is to use a module like Celery to perform async operations. Unfortunately, I do not have access to Celery as I cannot download new packages due to corporate policy.
main.py:
from flask import Flask, request, render_template, url_for, redirect
app = Flask(__name__, static_url_path = "/static", static_folder = "static")
#app.route("/", methods=['GET'])
def home():
return render_template("index.html")
#app.route("/in_progress", methods=['GET', 'POST'])
def in_progress():
if request.method == 'GET':
# Do the background processing here
return render_template('result.html') # This is the final part of the process
elif request.method == 'POST':
# Upload the files and do some pre-processing with the form
# This takes a couple of seconds so appears to not be doing anything for the user
# Want to render the GET 'in_progress.html' template at the top of this to give a better user experience
return render_template('in_progress.html') # Reloads same page using GET
index.html:
...some irrelevant HTML
<form action="{{ url_for('in_progress') }}" method="POST" id="form" name="form" enctype="multipart/form-data">
...other irrelevant HTML

Implementing File Uploads From Angular to Flask

I am trying to implement file uploading for my Web tool. The front end is developed using angular and the back end is using flask. Following tutorials on the flask website I have set up the following flask app:
from flask import Flask, request
from werkzeug import secure_filename
import os
UPLOAD_FOLDER = '/home/openstack/Documents/Confmrg/bcknd/uploads'
app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
#app.route('/uploader' , methods = ['GET' , 'POST'])
def upload_file():
if request.method == 'POST':
f = request.files['file']
filename = secure_filename(f.filename)
f.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
return 'File Uploaded'
if __name__ == '__main__':
app.run(debug = True)
I run this and the web server is hosted on http://localhost:5000
So on my angular component html I place the following:
<form action="http://localhost:5000/uploader" method="POST" enctype = "multipart/form-data">
<input type="file" name="file" />
<input type="submit" />
</form>
However when I run the angular web page, and test it by uploading a file and clicking submit, nothing happens. There is no error, and nothing is output in the console. I must be missing something, could someone point me in the right direction?
Form onSubmit handler
To answer your immediate question, what's happening is input type submit in Angular calls the onSubmit method of the form (instead of submitting the form like in plain HTML). And because you don't have a handler for onSubmit in your class, nothing is happening.
For a quick test, follow this link to create a simple onSubmit handler method to test that your submit button works.
Here's a Stackblitz example which logs to console when you click the submit button: https://stackblitz.com/edit/angular-uy481f
File upload
To make file upload work, you would need to make a few things. This touches the component class, creating a new service and injecting it, and updating your form to bind it to the class.
Create a proper Angular form. Here's an example.
Create a method that will handle the onSubmit() of the form.
Create a service that will handle Http calls to upload files.
Inject the service into your class, and call the file upload method of that class.
As you can see, there's a lot involved in making this work unlike having a simple post form in the template. As such, it will be too much for a single answer.
But hopefully, the initial paragraph answered your question and the rest of the answer pointed you in the right direction.

Provide standard data to Flask template

I would like to be able to generate a navbar based on an object's contents, basically having a navbar array or class that holds subpages and generates the appropriate navbar with collapsing parts etc. I have experience with Laravel in PHP which is similar to Flask but I can't figure out a way to do it easily. I would have to provide a set of data objects to every single page since it's part of the layout but would prefer not to have to specify it specifically for each page. Is there a way to do this?
So far I only have the basics, an app factory, view and blueprint:
Factory
def create_app():
app = Flask(__name__)
app.config.from_pyfile('config.py')
app.register_blueprint(blueprint_index)
return app
Blueprint
from flask import Blueprint, render_template, session
blueprint_index = Blueprint('simple_page', __name__)
#blueprint_index.route('/')
def index():
if 'text' in session:
session['text'] += 1
else:
session['text'] = 0
return render_template('pages/index.html', text=str(session['text']))
Ignore the little bit of debug text I added to the route.
You could do this with a context processor. Add this to the end of your blueprint code-block:
#blueprint_index.context_processor
def inject_text():
return dict(text=session['text'])
{{text}} will now be available within every template on that blueprint.

Is there a way to test if flask template contains a link?

I've been testing whether routes exist using
def test_index(self):
r = self.app.get("/")
self.assertEqual(200, r.status_code, "Status code was not 'OK'.")
My template has a hyperlink to another page. Is there a way to test if this exists?
Well, if you are testing templates, every template you render is the result of a request to some route. If you render url's in a template using url_for(), then it will raise a BuildError if the url is pointing to a non existing route, and the server will return the status code 500. Therefore, you don't need to parse your templates manually for testing purposes if you just check the route instead.
Example:
from flask import Flask, render_template_string
app = Flask(__name__)
#app.route('/index')
def index():
return render_template_string("""
{{ url_for('index') }}
{{ url_for('blabla') }}
""")
def test_index(self):
r = self.app.get("/index")
self.assertEqual(200, r.status_code, "Status code was not 'OK'.")
This will result in a
routing.BuildError: Could not build url for endpoint 'blabla'. Did you mean 'static' instead? error, which makes your tests fail.
I hope this explanation is clear enough!

Flash messaging not working in Flask

I have been unable to get the flash function to work in flask. Heres my code.
#!venv/bin/python3
from flask import Flask, flash
app = Flask(__name__)
app.config['SECRET_KEY'] = '12345'
#app.route('/')
def index():
flash('Hi')
return 'Hello'
if __name__ == '__main__':
app.run()
I expected this to flash a message saying hi but when I load the page no flash box appears. What am I not understanding here?
I think the main problem is that you're returning a string and not a render_template that handles the flash and converts it to a display message. Check out this documentation code here for an example of how to handle flashes
So I suggest trying: return render_template('index.html')
And then use the index.html file to set up your code that handles the flash message. I have a feeling that just returning a string, as you've done here, without somewhere for the code to understand the flash will give a null result.
#!venv/bin/python3
from flask import Flask, flash, redirect
app = Flask(__name__)
app.config['SECRET_KEY'] = '12345'
#app.route('/')
def index():
flash('Hi')
return redirect('index.html')
return render_template('index.html')
if __name__ == '__main__':
app.run()
ou can do following changes in your code import redirect and redirect it to any html page to show the flashed message.. in this case index.html
and in index.html page you have to use jinja template to get flash message and display it in page for that we use get_flashed_messages()
In index.html file add following code
<body>
{% for mesg in get_flashed_messages() %}
<h1>{{ mesg }}</h1>
{% endfor %}
</body>
It has been a while since the question was asked. I'll post my answer here since I got to this question somehow.
As Miguel Grinberg wrote in "Flask Web Development: Developing Web Applications with Python":
Calling flash() is not enough to get messages displayed; the
templates used by the application need to render these messages.
So anyone who have the same problem, just ensure, that you added the get_flashed_messages() function to the template and then displayed a message. For the reference you can look at:
Python Flask flash not working correctly,
and for sure Miguel Grinberg's book mentioned above, Chapter 4.
Hope this will be helpful.

Categories

Resources