I’m very new to Flask (and web development in general) but so far I think I’m sorta getting it?
anyway, I want to make a web app where the user uploads a file, the file will then be analyzed using Flask (mainly python and some shell) and the results then need to be reported back to the user.
I what have until now is a page where the user can upload their file and where a job id is assigned to the file. What I want next is that the users get redirected to a page with the jobid is the URL like
#app.route("/<jobid>", methods=['GET', 'POST’]) and that a loading page is displayed until the results files exist > then another page needs to be displayed.
The problem: I have no clue how to do that. This is what I got so far:
python:
#app.route("/<jobid>", methods=['GET', 'POST'])
def main_process(jobid):
if not jobid in JOBID_DICT:
return render_template("upload_fail.html")
else:
des = JOBID_DICT.get(jobid)
if request.method == "GET":
return render_template("complete.html", jobid=jobid)
if request.method == "POST": ##POST METHOD does not work yet
#this is where I need to run the analysis ig?
return render_template("results.html")
complete html:
{% extends "templates/base.html" %}
{% block title %}
succesfull upload
{% endblock %}
{% block main %}
<h1>file was uploaded</h1>
<p>starting process</p>
<p>once process is completed page will be refreshed.</p>
<p>Job ID: {{ jobid }} </p>
{% endblock %}
results.html:
{% extends "templates/base.html" %}
{% block title %}
{{jobid}}
{% endblock %}
{% block main %}
<h1>this the results page</h1>
<p>which I still need to code</p>
{% endblock %}
base.html (i use bootstrap and other css files but removed it for clarity):
<!doctype html>
<html lang="en">
<head>
<title> {% block title %}{% endblock %}</title>
</head>
<body>
<main>{% block main %}{% endblock %}</main>
</body>
</html>
If someone could help, it would be great. I mainly know python and R, and my HTML + CSS knowledge is from like 5 years ago… but I’m learning. Anyway thanks already.
You can use threading for that.
Put the job on a thread and when it completes update your UI
You can find more here threading
Related
I've been trying to use my custom 404- and 403 pages for my django project and I used code for it that I already used in other projects, but somehow it's not working yet.
This is my function:
def error_404(request, exception):
return render(request, 'main/errors/404.html', status=404)
And this is where i call the function in the urls.py:
handler404 = 'main_app.views.error_404'
This is my 404.html:
{% extends "../base.html" %}
{% load static %}
{% load i18n %}
<html>
<header>
{% block title %}<h1>404 - {% trans "Page not found" %}</h1>{% endblock %}
</header>
<main>
{% block content %}
<p>The page your looking for could not be found</p>
{% endblock %}
</main>
</html>
The pathes should actually be fine, since I used render(template_name=) alot in this project and I just copied it and changed the file name. I also set the DEBUG=False in the settings.py
Does anybody have an idea?
As far as I know, and this is the approach I always used, the way to do it is to simply create a 404.html page at root level in the templates folder.
I have 4 files:
flask_blog.py
from flask import Flask, render_template
app = Flask(__name__)
#app.route("/")
#app.route("/home")
def home_page():
return render_template("home.html")
#app.route("/about")
def about():
return render_template("about.html", title = "About")
layout.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
{% if title %}
<title>Flask Blog - {{ title }}</title>
{% else %}
<title>Flask Blog</title>
{% endif %}
</head>
<body>
{% block content %}{% endblock content %}
</body>
</html>
home.html
{% extends "layout.html" %}
{% block content %}{% endblock content %}
about.html
{% extends "layout.html" %}
{% block content %}{% endblock content %}
On my about page, the title is "Flask Blog - About", and in my home page, the title is "Flask blog". Now, this is happening due to the if/else statements in the layout.html file. The if/else statements are:
{% if title %}
<title>Flask Blog - {{ title }}</title>
{% else %}
<title>Flask Blog</title>
{% endif %}
Now, the value of the 'title' variable must be 0 or None, since we are going to the else statement for the home page. Now, my question is, we didn't assign a value to the 'title' variable beforehand. Better yet, we haven't even created the 'title' variable in the flask_blog.py file. How are we not getting a NameError? Shouldn't we get NameError: name 'title' is not defined?
Related
The templating language used by default in flask is Jinja. Jinja is not Python, and as such it works a little differently sometimes.
When a variable is not defined, if statements in Jinja template evaluate to False. As a result it doesn't throw an exception but instead it just goes to the next else block.
More specifically, an undefined variable becomes of type Undefined, which has it's own documentation page: https://jinja.palletsprojects.com/en/3.1.x/api/#undefined-types
This is useful in a templating language, because it makes it easier to re-use complex templates without having to specify every parameter every time you render it. If a parameter (and corresponding if block) is not relevant for a call to render_template, you can just omit it and don't worry about it.
When using HTMX framework with Python Flask, you have to be able to:
serve a request as a HTML fragment if it's done by HTMX (via AJAX)
server a request as a full page if it's done by the user (e.g. entered directly in the browser URL bar)
See Single-page-application with fixed header/footer with HTMX, with browsing URL history or Allow Manual Page Reloading
for more details.
How to do this with the Flask template system?
from flask import Flask, render_template, request
app = Flask("")
#app.route('/pages/<path>')
def main(path):
htmx_request = request.headers.get('HX-Request') is not None
return render_template(path + '.html', fullpage=not htmx_request)
app.run()
What's the standard way to output a full page (based on a parent template pagelayout.html):
{% extends "pagelayout.html" %}
{% block container %}
<button>Click me</button>
{% endblock %}
if fullpage is True, and just a HTML fragment:
<button>Click me</button>
if it is False?
This solution based on that we can use a dynamic variable when extending a base template. So depending on the type or the request, we use the full base template or a minimal base template that returns only our fragment's content.
Lets call our base template for fragments base-fragments.html:
{% block container %}
{% endblock %}
It's just returns the main block's content, nothing else. At the view function we have a new template variable baselayout, that contains the name of the base template depending on the request's type (originating from HTMX or not):
#app.route('/pages/<path>')
def main(path):
htmx_request = request.headers.get('HX-Request') is not None
baselayout = 'base-fragments.html' if htmx_request else 'pagelayout.html'
return render_template(path + '.html', baselayout=baselayout)
And in the page template, we use this baselayout variable at the extends:
{% extends baselayout %}
{% block container %}
<button>Click me</button>
{% endblock %}
As pointed in the section Null-Default Fallback of Jinja documentation, the extends tag can actually come in an if statement:
Jinja supports dynamic inheritance and does not distinguish between parent and child template as long as no extends tag is visited. While this leads to the surprising behavior that everything before the first extends tag including whitespace is printed out instead of being ignored, it can be used for a neat trick.
Usually child templates extend from one template that adds a basic HTML skeleton. However it’s possible to put the extends tag into an if tag to only extend from the layout template if the standalone variable evaluates to false which it does per default if it’s not defined. Additionally a very basic skeleton is added to the file so that if it’s indeed rendered with standalone set to True a very basic HTML skeleton is added:
{% if not standalone %}{% extends 'default.html' %}{% endif -%}
<!DOCTYPE html>
<title>{% block title %}The Page Title{% endblock %}</title>
<link rel="stylesheet" href="style.css" type="text/css">
{% block body %}
<p>This is the page body.</p>
{% endblock %}
Source: https://jinja.palletsprojects.com/en/3.0.x/tricks/#null-default-fallback
So, your requirement could be fulfilled doing:
{% if not fullpage %}{% extends 'pagelayout.html' %}{% endif -%}
{% block container -%}
<button>Click me</button>
{%- endblock %}
so I tried bulding a (small) website (for learning purposes) and had a few problems with the usage of a block.
I have the feeling that the problem is something obvious, but I can't figure it out.
Here is my code:
# main.py
from flask import Flask, render_template
app = Flask(__name__)
#app.route("/")
def home():
return render_template("main.html")
if __name__ == "__main__":
app.run(debug=True)
# main.html
<!DOCTYPE html>
<head>
<title>
{% block title %}{% endblock %}
</title>
</head>
<body>
{% block content %}{% endblock %}
</body>
</html>
# mainexdended.html
{% extends "main.html" %}
{% block title %}Test{% endblock %}
{% block content %}
<h1> Content Test </h1>
{% endblock %}
Now, when I run the code, I just get a blank page. Everything defined in the mainextended.html gets ignored.
How can I change that?
That's because you are rendering main.html, not mainextended.html.
You need to change
#app.route("/")
def home():
return render_template("mainextended.html")
Than you should see the contents of both, main.html and mainextended.html
If you use "extend" you always want to render the "extending" html, there is also a function to include content tho, which would work the other way round.
I'm new to programming. I decided to try to create a web app using flask, python, and HTML. I set up three files; two HTML and one python:
This is the HTML file that should have information replaced (didntwork.html):
<!doctype html>
<html>
<head>
<title>My Webpage</title>
</head>
<body>
<h3>Information:</h3>
{% block body %}{% endblock %}
</body>
</html>
.
This is the file that should input information to the first (connection.html):
{% extends 'didntwork.html' %}
{% block body %}
<h4>information content</h4>
{% endblock %}
.
Finally, this is the logic for the flask app in python (main.py):
from flask import Flask, render_template
app = Flask(__name__)
#app.route('/')
def index():
return render_template('didntwork.html')
if __name__ == '__main__':
app.run(debug=True)
Unfortunately, the extends in the second HTML file does not seem to be recognized, and the information in its block will not be replaced in the first HTML file (didntwork.html).
This is the output:
The expected outcome should append an h4 tag to the body with the phrase 'information content'.
Any help would be appreciated, thanks.
The problem is the {% extends 'didntwork.html' %}. From what I can tell the file that contains this code:
<!doctype html>
<html>
<head>
<title>My Webpage</title>
</head>
<body>
<h3>Information:</h3>
{% block body %}{% endblock %}
</body>
</html>
is your connection.html file.
You are extending to the same file you're rendering (didntwork.html). You have to change the extends line to extend your base html, connection.html in this case.
Use this code in your didntwork.html:
{% extends 'connection.html' %}
{% block body %}
<h4>information content</h4>
{% endblock %}
You can find more information in Template Inheritance
UPDATE BASE ON CLARIFICATION
You're rendering the wrong file in your route.
You should render the connection.html and this will extends your didntwork.html file.