I'm currently working on a web app in which I would like to display to the user whether they have visited the link already or not.
The code that displays the links is fairly simple, as seen below.
<ul>
<li>google</li>
<li>facebook</li>
<li>amazon</li>
</ul>
What I would like is to visualize that a link has been clicked by just adding a checkmark, or something along those lines, to the right of the link. How would I go about doing that? I'm working with Django for this project so a Django-specific solution would be great.
A very simple technique would be to use CSS :visited selector (if you don't want to use JavaScript). Check out this link for how you can use this selector in CSS.
You can basically add a checkmark in your HTML and set it's color same as background color (so that it doesn't show up). And, then change it to some other color when the link is visited. Check out the attached snippet.
a span {
color: white;
}
a:visited span {
color: black;
}
<ul>
<li>google<span>✓</span></li>
<li>facebook<span>✓</span></li>
<li>amazon<span>✓</span></li>
</ul>
I haven't used Django before, but I have some websites using Flask, so I can understand a few parts. I'll add my answer in Flask and hopefully you can translate that into Django. Sorry about that :/
I think you can make this work by using Jinja and some simple HTML.
I made some changes because links will just redirect you outside of your page, so your checkmarks wont be seen
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
</head>
<body>
<form action="/" method="POST">
<button name="google_" value="Google">Google</button>{% if _google %}✔{% endif %}
<br>
<button name="fb_" value="Facebook">Facebook</button>{% if _fb %}✔{% endif %}
</form>
</body>
</html>
the code in Flask would look like this:
from flask import Flask, render_template, request
app = Flask(__name__)
#app.route("/", methods=["GET", "POST"])
def home():
if request.method == "POST":
if request.form.get("google_", False) == "Google":
_google = True
return render_template("test.html", _google=_google)
elif request.form.get("fb_", False) == "Facebook":
_fb = True
return render_template("Test.html", _fb=_fb)
return render_template("Test.html")
if __name__ == "__main__":
app.run(debug=True, host="localhost", port=5000)
Screenshots:
I didn't really made it look nice but it works :/
Again sorry for making it into Flask. I don't have any experience with Django.
Related
Plotly Dash uses the index_string value to customize the Dash's HTML Index Template as explained here.
To integrate Dash with Flask, one can pass Flask app as Dash server, and get back the Flask app with the Dash app integrated in it, also taking advantage of Jinja. This approach is nicely explained in several tutorial, such as this one.
If you want to add a Jinja template, you can pass the HTML template to the code initializing Dash. The index string shall contain the {%" + filed + "%} required by Dash, but rendering the template will escape that code.
A trick is nicely explained in an answer here, where the HTML is enriched with comments, which are ignored by Jinja during the rendering, and then replaced in the code with the fields for Dash before setting the index_string upon Dash app initialization.
This effectively works, the dash app is well integrated in the Flask server, and the Jinja template is inegrated and rendered.
Here some code to frame this a bit more concretely:
def init_dashboard(server,url):
"""Create a Plotly Dash dashboard."""
dash_app = dash.Dash(
server=server,
routes_pathname_prefix=url,
external_stylesheets=[
"/static/dist/css/styles.css",
"https://fonts.googleapis.com/css?family=Lato",
],
)
# Both app context and a request context to use url_for() in the Jinja2 templates are needed
with server.app_context(), server.test_request_context():
#items = Item.query.all()
html_body = render_template_string(html_layout)
comments_to_replace = ("metas", "title", "favicon", "css", "app_entry", "config", "scripts", "renderer")
for comment in comments_to_replace:
html_body = html_body.replace(f"<!-- {comment} -->", "{%" + comment + "%}")
dash_app.index_string = html_body
# Load DataFrame
df = create_dataframe()
# Create Layout
dash_app.layout = my_layout
init_callbacks(dash_app)
return dash_app.server
With the layout in HTML:
html_layout = """
{% extends "base.html" %}
{% block title %}
Calculator
{% endblock %}
{% block content %}
<body class="dash-template">
<header>
<div class="nav-wrapper">
<!-- <a href="/">
<img src="/static/img/logo.png" class="logo" />
<h1>Plotly Dash Flask Tutorial</h1>
</a> -->
<nav>
</nav>
</div>
</header>
<!-- app_entry -->
<footer>
<!-- config -->
<!-- scripts -->
<!-- renderer -->
</footer>
</body>
{% endblock %}
"""
Now, the problem I have is that I would like to update the index_string in the Dash_app during the execution, for example during a callback, and not only on initialization.
Upon debug, I can get the dash_app embedded in the Flask app with the dash.get_app() function. There, I can find my index_string nicely set. But I could not find a way to set back that index_string value, effectively updating the dash template. Do you have any idea on how I could achieve this feature?
Ok, I found a solution, but it is super hacky, and I really would like something a bit more robust and elegant, so whoever has an idea, please share it!
The solution is by setting your index_page like this: your app exists in dash.dcc._dash._get_app.APP
You can modify it from within a dash callback code, from where the variable is visible.
and you can set the index_page attribute directly in the dash_app using setattr like this:
html_body = render_template_string(html_layout, variable_for_jinja=value)
comments_to_replace = ("metas", "title", "favicon", "css", "app_entry", "config", "scripts", "renderer")
for comment in comments_to_replace:
html_body = html_body.replace(f"<!-- {comment} -->", "{%" + comment + "%}")
setattr(dash.dcc._dash._get_app.APP,"index_string",new_index_page)
Any findings on this? I'm also having similar use case.
I've been working myself through CS50 lately but now I'm struggling with my final project. One of the key elements is to allow users to upload images from an html website while the image will be further processed via an application.py. Overall I'll use flask.
Unfortunately this is where I'm already struggling. I tried all ways I could find to upload pictures and the result is always similar, when pressing the submit-button I receive an Internal Server Error message. I even copied code from youtube or forums which worked fine in the video but not in my IDE. Is it possible that the CS50 IDE blocks file uploads in general?
If not I isolate the problem to the code below and would highly appreciate if you could have a quick look. Probably it's a tiny problem I just don't get.
Code in my application.py
from flask import Flask, render_template, request
app = Flask(__name__)
#app.route("/")
def index():
return render_template("index.html")
#app.route("/upload", methods=["POST"])
def upload():
file = request.files["inputFile"]
return file.filename
if __name__ == "__main__":
app.run(debug=True)
Code in the index.html
<!DOCTYPE html>
<html lang="en">
<head>
FILE UPLOAD EXAMPLE
</head>
<body>
<div class="container">
<h1>File Input</h1>
<form method="POST" action="/upload" enctype="multipart/form-data">
<div class="form-group">
<label for="inputFile">File input</label>
<input type="file" name="inputFile">
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
</div>
</body>
I tried to isolate the problem and one thing I found is that the form always returns "GET" when the submit button is pressed while it is specifically defined in the form method that return should be "POST.
Anyhow, thank you so much for any comments in advance!
Best,
Martin
It works when you have templates directory in your project structure.
myproject/
__init__.py
app.py
templates/
index.html
This is because Flask's default template path is templates.
if you want to change it to something else for ex 'my_templates' then you should override it while creating app.
app = Flask(__name__, template_folder='my_templates')
Btw there is no real DB/file store code return so it will just return you the filename as response.
I am new to Flask. I want to run my Python project, when the start button is pressed from the HTML page and display the string which is returned from the Python code, on the HTML page. I am using Python flask.
This is the HTML file with the button.(The name of the HTML file is json.html)
<!DOCTYPE html>
<html>
<body>
<h1>Smart Job Interviewer</h1>
<button type="button">Start the Interview</button>
</body>
</html>
Following is the Python flask file. newexecutiontest is my python file and run() is the function that I need to run. This function returns a string and I want to display it on the HTML page.
from flask import Flask
from TextToSpeech import newexecutiontest
from flask import render_template
app = Flask(__name__)
#app.route('/')
def index():
return render_template('json.html')
def dynamic_page():
return newexecutiontest.run()
if __name__ == '__main__':
app.run(host='0.0.0.0', port='8000', debug=True)
When I run the code and load the web page it says that "This site can't be reached"
Can someone please help me to achieve the above task.
Thank you in advance.
Try changing the IP to localhost or 127.0.0.1
You should keep the html template under the folder /templates
You could make the button part of a form, so that it is routed back to your python module on click (just printing a string on button click could more easily be done with javascript, but I assume run() performs some logic as well). Also add some input field to the form so you can know it was submitted:
<form method="GET">
<input type="hidden" name="start">
<button type="submit">Start the Interview</button>
</form>
Now in the flask file, you can perform a basic check to see if "start", or whatever name you gave your input, exists in the get request arguments - which would mean the form was submitted. It is possible to pass arguments to an html file, so we will pass None if the form wasn't submitted or the desired string if it was:
from flask import request
#app.route('/')
def index():
return render_template('json.html', test_str=dynamic_page() if request.args.get("start") is not None else None)
And finally, you can check the value of test_str in the html file and print it accordingly, using the jinja templating engine. Logic is declared between {% and %}, while evaluations are declared between {{ and }}. Adding this to the html file where you want the string to be printed should work:
{% if test_str is not none %}
<p>{{ test_str }}</p>
{% endif %}
I want to pass variables from a site to another.
This is no problem, as there are many ways to do it.
I'm struggling though, in how I can 'hide' these variables in the URL, and yet be able to get the values.
Ex.:
If I use 'request.args.get':
#page.route('/users', methods=['GET', 'POST'])
def users():
user = request.args.get('user')
return render_template('users.html', user=user)
When I click in the link, the URL generated is:
http://localhost:5000/users?user=john
My goal is to access the 'users' page, in the 'John' section, but what the user will see in the URL path is only http://localhost:5000/users
I was able to achieve my goal using:
window.history.pushState({"html":response.html,"pageTitle":response.pageTitle},"", "/users/");
I'm no Web Dev'er, just a Python/Flask enthusiast and know that 'window.history.pushState()' is meant for other purposes. I'm also aware that it a HTML5 Feature and not all browsers are compatible. But hey, it did the trick ;) .
Unless someone point out reasons I shouldn't be using this approach, this is my solution.
Thanks all for your time
If you'd only want to hide the variable name then you could use converters to create a route like 'users/<str:username>'. Your url would be http://localhost:5000/users/john.
Your can find the documentation here: http://exploreflask.com/en/latest/views.html#built-in-converters
Note that hiding the variables completely would mean, that your users would lose the ability to bookmark the page they are on. Additionaly if they bookmark /users anyways, you would have to catch the case that your variable is not sent or run into errors.
Post method can hide data and variables from URL. So you need to integrate it in your project. Here is an example.
app.py:
from flask import Flask, render_template, request
app = Flask(__name__)
#app.route('/users', methods=['GET', 'POST'])
def show_users():
if request.method == 'POST':
username = request.form.get("username", None)
return render_template('post_example.html', username = username)
else:
return render_template('post_example.html')
if __name__ == '__main__':
app.run(debug = True)
post_example.html:
<html>
<head></head>
<body>
{% if username %}
Passed username: {{ username }}
{% endif %}
<form action="/users" method="post">
Username: <input type="text" name="username">
<input type="submit" name="submit" value="Submit">
</form>
</body>
</html>
Output:
You can check the HTTP methods in Flask official documentation here
I am making a web app using Python and have a variable that I want to display on an HTML page. How can I go about doing so? Would using {% VariableName %} in the HTML page be the right approach to this?
This is very clearly explained in the Flask documentation so I recommend that you read it for a full understanding, but here is a very simple example of rendering template variables.
HTML template file stored in templates/index.html:
<html>
<body>
<p>Here is my variable: {{ variable }}</p>
</body>
</html>
And the simple Flask app:
from flask import Flask, render_template
app = Flask('testapp')
#app.route('/')
def index():
return render_template('index.html', variable='12345')
if __name__ == '__main__':
app.run()
Run this script and visit http://127.0.0.1:5000/ in your browser. You should see the value of variable rendered as 12345