Flask & jQuery: Image-picker doesn't show the pictures - python

1. Background:
I am new to Flask, JavaScript or web development. I am currently trying to build an interface for a project of mine, which does extract the linear area of a curve. So far so good, my python code works: It reads data from an .csv or .xlsx file and returns the area, it's slope and plots for each sample. Now I am desperately trying to put them in some kind of user interface, so you can decide which ones to plot. I recognized image-picker (github.com/rvera/image-picker) as a suitable tool for the job, so I decided to implement it into my project. For this I started to build a simple test-page with the image-picker.
2. Problem
Unfortunately, I wasn't able to achieve this. Instead of seeing a list of the image names followed by the pictures, I can only get the list. I will add screenshots of the outcomes.
3. My Code
The project structure
Both, image-picker.css and image-picker.js are taken from the image-picker github
base.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="{{ url_for('static', filename = 'css/main.css') }}">
{% block head %} {% endblock %}
</head>
<body>
{% block body %} {% endblock %}
</body>
</html>
img_picker.html
{% extends 'base.html' %}
{% block head %}<title>Image Picker</title> {% endblock %}
<meta charset="utf-8">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='image-picker.css') }}">
<script src="{{ url_for('static', filename='image-picker.js') }}" type="text/javascript"></script>
{% block body %}
<select multiple="multiple" class="image-picker show-html">
<option data-img-src='http://placekitten.com/220/200' value='1'>Cute Kitten 1</option>
<option data-img-src='http://placekitten.com/180/200' value='2'>Cute Kitten 2</option>
<option data-img-src='http://placekitten.com/130/200' value='3'>Cute Kitten 3</option>
<option data-img-src='http://placekitten.com/270/200' value='4'>Cute Kitten 4</option>
</select>
<script> $('.image-picker').imagepicker();
</script>
{% endblock %}
app.py
from flask import Flask, render_template
app = Flask(__name__)
#app.route('/')
def index():
return render_template('img_picker.html')
if __name__ == '__main__':
app.run()
main.css
body{
margin: 0;
font-family: sans-serif;
}
table {
font-family: arial, sans-serif;
border-collapse: collapse;
width: 100%;
}
td, th {
border: 1px solid #dddddd;
text-align: left;
padding: 8px;
}
tr:nth-child(even) {
background-color: #dddddd;
}
How it looks
How it should look
(The website I took the example from: https://rvera.github.io/image-picker/)
If you need any more information, I will be glad to provide it. There has been another question regarding this problem before, but it wasn't solved.
Thanks for any help,
Carroll

Related

Adding CSS loader to HTML button click

I'm trying to add a "loader" while my flask application runs a task.
Here is my HTML for for my button
{% extends "base.html" %}
{% block head %}
{# <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='styles/leaf.css') }}"> #}
{% endblock %}
{% block content %}
<div id="loader"></div>
<div id="vo_budget_file_settings">
{# Upload Final CRO Budget File #}
<p>Please upload the final CRO budget File</p>
<form class="" action="/generatecleanbudgetfile" method=POST enctype=multipart/form-data>
<input type="file" name="data_file" accept=".xls, .xlsx, .xlsm"/>
<input type="submit" value="Begin Format" onclick="loading();"/>
</form>
</div>
<script type="text/javascript">
function loading(){
$("#loader").show();
}
</script>
{% endblock %}
Here is the CSS that I've added:
#loader {
border: 16px solid #f3f3f3; /* Light grey */
border-top: 16px solid #3498db; /* Blue */
border-radius: 50%;
width: 120px;
height: 120px;
animation: spin 2s linear infinite;
}
#keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
Any ideas on how to call this correctly?
Make it visible from the start, without ever showing it with javascript. Then hide it with js like so:
$(document).ready(() => {
$("#loader").hide();
})
EDIT: I now realize you said on button click in the title. I am assuming you want to hide the loading screen on button click? If not correct me in a comment. Otherwise, use this code:
$("#button").click(() => {
$("#loader").hide();
})
P.S.
Your script should be at the bottom of the body, and your CSS and JS (and my code) reference #loader, when the body has <div id="loading">

jinja2.exceptions.TemplateSyntaxError: expected token 'end of print statement', got '='

Respected Members,
I'm creating a basic login page sans the DB setup. I'm not sure what I'm doing wrong while passing the jinja templates to the html file.
The .py file:
from flask import Flask, render_template, flash, session, redirect, url_for
from flask_wtf import FlaskForm
from wtforms import StringField,SubmitField
from wtforms.validators import DataRequired
app = Flask(__name__)
app.config['SECRET_KEY'] = 'kmykey'
class SimpleForm(FlaskForm):
username = StringField("Username:", validators=[DataRequired()])
password = StringField("Password:", validators=[DataRequired()])
submit = SubmitField("Submit")
#app.route('/', methods = ['GET', 'POST'])
def index():
form = SimpleForm()
if form.validate_on_submit():
session['username'] = form.username.data
session['password'] = form.password.data
return redirect(url_for('index'))
return render_template('Login_Page1.html', form=form)
if __name__ == '__main__':
app.run()
The html file:
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>Ticket Booking</title>
<link rel="stylesheet" type= "text/css" href=" {{ url_for('static',filename='Login_Page1.css') }}">
<link href="https://fonts.googleapis.com/css2?family=Anton&display=swap" rel="stylesheet">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">
<!-- JS, Popper.js, and jQuery -->
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js#1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js" integrity="sha384-OgVRvuATP1z7JjHLkuOU7Xw704+h835Lr+6QL9UvYjZE3Ipu6Tp75j7Bh/kR0JKI" crossorigin="anonymous"></script>
</head>
<body>
<div align="center" class="main1">
<form method="POST">
<h1>Railway Booking Portal</h1>
<h2>Welcome!</h2>
<br>
{# This hidden_tag is a CSRF security feature. #}
{{ form.hidden_tag() }}
{{ form.username.label, extra_classes='uname1' }} {{ form.username(placeholder='email here') }}
<br>
{{ form.password.label, extra_classes='passwd1' }} {{ form.password}}
<br>
<a class="abc" href="Sign_Up.html"><u>SignUp</u></a>
<br>
<a class="abc1" href="Password_Reset.html"><u>ForgotPassword</u></a>
<br>
<br>
{{ form.submit() }}
<br>
<p>"One's destination is never a place, but a new way of seeing things." - Henry Miller</p>
</form>
</div>
The css file:
body{
background: url(railway-tracks.jpeg);
background-repeat: no-repeat;
}
h1{
color: black;
}
p{
font-family: 'Anton', sans-serif;
font-size: 200%;
color: black;
}
.uname1{
display: inline-block;
min-width: 90px;
color: red;
}
.passwd1{
display: inline-block;
min-width: 90px;
color: red;
}
.main1{
background-color: rgba(255, 255, 255, 0.6);
}
.abc{
color: black;
}
.abc1{
color: black;
}
Kindly guide, what is the part that I've done wrong.
I also tried inject the wtf form's attributes to html via (also used class instead of class_):
{{ form.username.label(class_='uname') }} {{ form.username(placeholder='email here') }}
{{ form.password.label(class_='passwd') }} {{ form.password}}
Although didn't receive an error, and successfully flask app ran and the page was shown with all relevant syling/formatting, but the labels weren't formatted.
You can see the answer here
Updated for WTForms 2.1
You can now as of WTForms 2.1 (December 2015) set rendering keywords by using the render_kw= parameter to the field constructor.
So the field would look like:
abc = StringField('abc', [InputRequired()], render_kw={"placeholder": "test"})
(Old answer, still true for versions older than WTForms 2.1)
placeholder is not supported in the Python constructor in WTforms 2.0.x and below.
However, you can do this easily in your template:
{{ form.abc(placeholder="test") }}
You can see the answer here
Change code, i use pycharm and see that
{{ form.username.label(extra_classes='uname1') }} {{ form.username(placeholder='email here') }}
<br>
{{ form.password.label(extra_classes='passwd1') }} {{ form.password}}
Updated for WTForms 2.1
You can now as of WTForms 2.1 (December 2015) set rendering keywords by using the render_kw= parameter to the field constructor.
So the field would look like:
abc = StringField('abc', [InputRequired()], render_kw={"placeholder": "test"})
(Old answer, still true for versions older than WTForms 2.1)
placeholder is not supported in the Python constructor in WTforms 2.0.x and below.
However, you can do this easily in your template:
{{ form.abc(placeholder="test") }}

CSS isn't linking from my Python/Flask application

Can't seem to get my style sheet to link, can someone please tell me why?
I'm trying to set up an sample instance with a database, ran on Flask.
I thought it was my folder location, but I've double checked it is on the right place and can't figure out why, spent hours trying to fix it.
My HTML:
{% extends "layout.html" %}
{% block title %}
CS50_Web_Project1
{% endblock %}
{% block body %}
<h1>Login to CS50_Web_Project1</h1>
<form action="{{ url_for('register') }}" method="POST">
<button>Register</button>
</form>
{% endblock %}
My layout.html:
<!DOCTYPE html>
<html>
<head>
<title>{% block title %}{% endblock %}</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Zug+QiDoJOrZ5t4lssLdxGhVrurbmBWopoEl+M6BdEfwnCJZtKxi1KgxUyJq13dy" crossorigin="anonymous">
<!-- #olaf: own link to own style sheet-->
<link rel="stylesheet" href="css/style.css" type="text/css" >
<!-- #olaf: copied from https://bootsnipp.com/snippets/GaEOX-->
<link href="//maxcdn.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css" rel="stylesheet" id="bootstrap-css">
<script src="//maxcdn.bootstrapcdn.com/bootstrap/4.1.1/js/bootstrap.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
</head>
<body>
<div class="container">
{% block body %}
{% endblock %}
</div>
</body>
</html>
My CSS in css/style.css location:
/* style.css */
.note
{
text-align: center;
height: 80px;
background: -webkit-linear-gradient(left, #0072ff, #8811c5);
color: #fff;
font-weight: bold;
line-height: 80px;
}
.form-content
{
padding: 5%;
border: 1px solid #ced4da;
margin-bottom: 2%;
}
.form-control{
border-radius:1.5rem;
}
.btnSubmit
{
border:none;
border-radius:1.5rem;
padding: 1%;
width: 20%;
cursor: pointer;
background: #0062cc;
color: #fff;
}
My application.py:
import os
from flask import Flask, session, render_template, jsonify, request
from flask_session import Session
from sqlalchemy import create_engine
from sqlalchemy.orm import scoped_session, sessionmaker
app = Flask(__name__)
#from the internet...# app.config['DATABASE_URL'] = "path_to_db"
# Check for environment variable
if not "DATABASE_URL":
raise RuntimeError("DATABASE_URL is not set")
# Configure session to use filesystem
app.config["SESSION_PERMANENT"] = False
app.config["SESSION_TYPE"] = "filesystem"
Session(app)
# Set up database
engine = create_engine("DATABASE_URL")
db = scoped_session(sessionmaker(bind=engine))
#olaf: create a login page that has a form, containing "login" & "register" button
#app.route("/")
def index():
return render_template("index.html")
#olaf: Login button
#app.route("/register", methods=["POST"])
def register():
"""Register for the site"""
return render_template("registerSuccess.html")
To provide CSS file in your Flask template you need to use a specific method for that in your HTML template {{ url_for(STATIC_DIR_NAME, filename=PATH_TO_FILE_IN_STATIC_DIR)}}.
In your layout.html
<!DOCTYPE html>
<html>
<head>
<title>{% block title %}{% endblock %}</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Zug+QiDoJOrZ5t4lssLdxGhVrurbmBWopoEl+M6BdEfwnCJZtKxi1KgxUyJq13dy" crossorigin="anonymous">
<!-- #olaf: own link to own style sheet-->
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}" type="text/css" >
<!-- #olaf: copied from https://bootsnipp.com/snippets/GaEOX-->
<link href="//maxcdn.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css" rel="stylesheet" id="bootstrap-css">
<script src="//maxcdn.bootstrapcdn.com/bootstrap/4.1.1/js/bootstrap.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
</head>
<body>
<div class="container">
{% block body %}
{% endblock %}
</div>
</body>
</html>
Also, if you follow the official documentation tips on the layout should do it.
But if you have a custom project setup then you might need to provide to your app where a static folder is.
For example in your application.py
import os
from flask import Flask, session, render_template, jsonify, request
from flask_session import Session
from sqlalchemy import create_engine
from sqlalchemy.orm import scoped_session, sessionmaker
THIS_DIR = os.path.dirname(os.path.abspath(__file__))
STATIC_DIR = os.path.join(THIS_DIR, 'specific_path_to_static', 'static')
app = Flask(__name__, static_url_path=STATIC_DIR)
#from the internet...# app.config['DATABASE_URL'] = "path_to_db"
# Check for environment variable
if not "DATABASE_URL":
raise RuntimeError("DATABASE_URL is not set")
# Configure session to use filesystem
app.config["SESSION_PERMANENT"] = False
app.config["SESSION_TYPE"] = "filesystem"
Session(app)
# Set up database
engine = create_engine("DATABASE_URL")
db = scoped_session(sessionmaker(bind=engine))
#olaf: create a login page that has a form, containing "login" & "register" button
#app.route("/")
def index():
return render_template("index.html")
#olaf: Login button
#app.route("/register", methods=["POST"])
def register():
"""Register for the site"""
return render_template("registerSuccess.html")
Then the flask template should find the style.css file provided in layout.html file.
The first solution i can propose is that you download the bootstrap files and have them on your local working directory, then make a folder to contain static files and try the following code
<link href="{{ url_for('static', filename='css/bootstrap.min.css') }}" rel="stylesheet">

Difference in css outcome between static and jinja2 html

I am using Flask and therefore Jinja2 to dynamically create a web page.
When I use the render_template function the resulting web pages pick up my css styles normally and do as I expect with some strange exceptions.
For example, the following css and html code is working 100% as intended:
CSS:
.intro {
font-family: monospace;
font-size: 24px;
color: #455934;
padding-top: 30px;
padding-right: 50px;
padding-bottom: 5px;
padding-left: 50px;
}
HTML:
<p class ='intro'>
Hello
</p>
However when using a ``Jinja2``` template:
<p class ='intro'>
{{title}}
</p>
The css style for this class is ignored.
This is not true for any other styles in the same css file and template, for reference the whole template looks like this and the styles for div containers, background, etc. work as intended:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link rel= "stylesheet" type= "text/css" href= "{{ url_for('static',filename='gemuese_style.css') }}">
<title>{{title}}</title>
</head>
<body>
<div class="outer">
<div class="middle">
<div class="inner">
<p class ='intro'>
{{title}}
</p>
<ul>
<li>{{result}}</a></li>
</ul>
</div>
</div>
</div>
</body>
</html>
Edit:
Some testing has shown me that the style seems to work depending on the variable jinja renders. The template is rendered based on the output of different functions who generally return a list of a string and another list. The string is then used to fill in the {{title}} part where the css is failing.
For some functions it does work but I am not sure why because there is no difference in the return format.
Edit2:
Look at the difference between This rendered template and this one.

Loading URLs into an iFrame using Flask

I'm new to Flask and
I'm trying to create a Stumbleupon like website but I'm having problems while loading the content into an iFrame. I just cant figure it out how to iterate through each url and load them into the iFrame while clicking in the <a> tag.
Here is what I've done:
app.py
from flask import Flask, render_template
app = Flask(__name__)
#app.route("/")
def index():
urls = [
'http://www.w3schools.com',
'http://techcrunch.com/',
'https://www.fayerwayer.com/',
]
return render_template('index.html', urls=urls)
if __name__ == "__main__":
app.run(debug=True)
templates/layout.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<link rel="stylesheet" type="text/css" href="/static/css/normalize.css"/>
<link rel="stylesheet" type="text/css" href="/static/css/foundation.css"/>
</head>
<body>
<nav class="top-bar">
<h3 align="center">Stumble</h3>
</nav>
{% block content %}
{% endblock content %}
</body>
</html>
templates/index.html
{% extends 'layout.html' %}
{% block content %}
<iframe frameborder='0' noresize='noresize' style='position: absolute; background: transparent; width: 100%; height:100%;' src="????????" frameborder="0"></iframe>
{% endblock content %}
After adding import random at the top of your app.py file you could structure your code like this:
def index():
urls = [
'http://www.w3schools.com',
'http://techcrunch.com/',
'https://www.fayerwayer.com/',
]
iframe = random.choice(urls)
return render_template('index.html', iframe=iframe)
Then access the value in your template:
<iframe frameborder='0' noresize='noresize' style='position: absolute; background: transparent; width: 100%; height:100%;' src="{{ iframe }}" frameborder="0"></iframe>
And simply set the Stumble button to refresh the page.
<h3 align="center">Stumble</h3>
This will be pretty basic, but it will have the behaviour you're describing.
An improvement will be to use the session object to make sure that two subsequent requests do not display the same page inside the iframe.

Categories