I'm writing a small application in Flask.
run.py
#!flask/bin/python
from app import app
app.run(debug=True, port=9001)
init.py
from flask import Flask
app = Flask(__name__)
from app import views
index.html
{% extends "base.html" %}
{% block content %}
<select id = "foo">
{% for item in Citydata %}
<option value = {{ item.link }}> {{ item.name }} </option>
{% endfor %}
</select>
Click here
{% endblock %}
new.html
{% extends "base.html" %}
{% block content %}
<p>gafgafgadfgaerwgtdfzgaergdfzgaergaergaergt</p>
{% endblock %}
and lastly views.py
from flask import render_template
from app import app
from bs4 import BeautifulSoup
import urllib2
import traceback
class City_Link(object):
name = ""
link = ""
# The class "constructor" - It's actually an initializer
def __init__(self, name, link):
self.name = name
self.link = link
#app.route('/')
#app.route('/index')
def index():
URL = 'http://www.amis.pk/DistrictCities.aspx'
City_Data = scrape(URL)
return render_template("index.html",
title='Home',
Citydata=City_Data)
#app.route('/new/<data>', methods=['GET', 'POST'])
def new(data):
return render_template("new.html",
title='Home',
link = data)
def scrape(url):
data = []
try:
page = urllib2.urlopen(url)
soup = BeautifulSoup(page.read(), "lxml")
table = soup.body.find(id='TABLE1')
for row in table.findAll("tr"):
heads = row.findAll("a")
for head in heads:
data.append((City_Link(head.text.strip(), head.attrs['href'])))
except:
print(traceback.format_exc())
return data
When i click on the "Click me" href in index.html It gives me a 404 not found on the template new.html. I dont understand why because I followed a basic tutorial. I tried changing ports and it worked. But then I tried to update the code and it broke the link again.
So the reason this happens is because flask registers /new and /new/ to be two different routes.
It also looks like you're not actually passing in any data to the data variable anyway. You can temporarily fix this issue by changing your link to point to
/new/something
But that doesn't totally address the problem. I recommend adjusting your template code to make use of flasks excellent url_for function. You can find the extended documentation for it here: http://flask.pocoo.org/docs/0.10/api/#flask.url_for
When we adjust your code, it should look like:
Click here
And that data variable looks like it's not even used! Let's just strip it out totally!
#app.route('/new', methods=['GET', 'POST'])
def new():
return render_template("new.html",
title='Home')
This has altered your code, and I may not have enough information about your use case. If this modifies it beyond being usable for your application, let me know and I'll adjust my answer accordingly.
Related
I have a CSV file called random.csv which I want to render on a html page if the user is logged in. I've tried using tablib for this.
__init__.py
from flask import Flask
import tablib
app = Flask(__name__)
dataset = tablib.Dataset()
with open(os.path.join(os.path.dirname(__file__), 'random.csv')) as f:
dataset.csv = f.read()
routes.py
#app.route('/dataset', methods=['GET', 'POST'])
#login_required
def dataset():
return dataset.html
This is the index.html file from where I want to link to the html page for the csv file.
{% extends "base.html" %}
{% block content %}
<p>Click to see CSV </p>
{% endblock %}
And this is the dataset.html file where I want to see the CSV data.
{% extends "base.html" %}
{% block content %}
{% endblock %}
I'm getting this error:
AttributeError: 'function' object has no attribute 'html'
The error is on the line in routes.py file where I return the dataset.html file.
I solved it by using pandas instead tablib. In my routes.py file just did this:
import pandas as pd
#app.route('/dataset', methods=['GET', 'POST'])
#login_required
def dataset():
table = pd.read_csv('filepath', encoding= 'unicode_escape')
return render_template("dataset.html", data=table.to_html())
The reason is that you shadowed whatever the variable was with the function name:
def dataset():
return dataset.html
dataset is the function. If it was something else before, naming your function dataset replaced whatever that variable was.
This question already has answers here:
Are global variables thread-safe in Flask? How do I share data between requests?
(4 answers)
Closed 2 years ago.
I want to constantly update my list stuff by appending more "stuff" in it. However, my list is not updating (preferably every second, but I don't know how to do a while loop inside flask).
Here is my routes.py :
from flask import render_template
from app import app
from win32gui import GetWindowText, GetForegroundWindow
#app.route('/')
#app.route('/index')
def index():
user = {'username': 'Miguel'}
stuff = []
stuff.append(GetWindowText(GetForegroundWindow()))
return render_template('index.html', title='Home', user=user, stuff = stuff)
if __name__ == "__main__":
app.run(debug=True)
Here is my index.html :
<html>
<head>
{% if title %}
<title>{{ title }} - Microblog</title>
{% else %}
<title>Welcome to Microblog!</title>
{% endif %}
</head>
<body>
<h1>Hello, {{ user.username }}!</h1>
<h1>Here: </h1>
{% for item in stuff %}
<p> {{ item }} </p>
{% endfor %}
</body>
</html>
When I flask run, there is only ever one item in the list. How do I let the program know I want to continue adding more items? I would like to achieve this in the index() function.
Thank you for your help!
Every time your index method is called, the local variable stuff gets re-initialised to an empty list and then you append an element to it. That's why every time you refresh the page, you only see this one newly added element in stuff.
Consider making stuff global and then add items to it:
from flask import render_template
from app import app
from win32gui import GetWindowText, GetForegroundWindow
stuff = []
#app.route('/')
#app.route('/index')
def index():
global stuff
user = {'username': 'Miguel'}
stuff.append(GetWindowText(GetForegroundWindow()))
return render_template('index.html', title='Home', user=user, stuff = stuff)
if __name__ == "__main__":
app.run(debug=True)
Or store global variables in a more better way.
I need to pass variable through jinja2 to base html template. If requesting python function test happens by URl - then everything is working okay. But I do need to request pyton function send_user_login_status each time when URL is changed. In this case it does not work. How can I achieve python function send_user_login_status executes every time when user changes URL and passing variable through jinja2 to .html file.
I am using flask.
base.html
<li class="{{ login_status_class }}"> {{ login_status }}</li>
test.html
{% extends "base.html" %}
Python function is working by URL correctly
#app.route('/test')
def test_api():
login_status_class = 'login'
login_status = u'Enter'
return render_template("base.html",
login_status=login_status,
login_status_class=login_status_class)
Python function has to work each time when URL changes
def send_user_login_status():
login_status_class = 'login'
login_status = u'Enter'
return render_template("base.html",
login_status=login_status,
login_status_class=login_status_class)
EDIT 1
For example, I'm trying to call a function send_user_login_status when user goes to the home page. But nothing happens.
#app.route('/')
def home():
send_user_login_status()
return render_template("index.html")
I'm making a Flask app that takes a single input from a user, and then uses that input to query an API, and return the results.
I'm trying to use the same template for both getting the user input, and displaying the results.
My return render template looks like this:
return render_template("query.html", json_data=json_data, info=info)
The problem is that when the page first loads, it's looking for the json_data, and info variables, but they don't exist yet.
I tried doing this:
data = request.args.get("t")
if data:
...
return render_template("query.html", json_data=json_data, info=info)
else:
return render_template("meter_mdm.html", json_data=None, info=None)
And then in my Jinja template, I put:
{% if json_data is not none and info is not none %}
...HTML that uses the json_data and info variables
{% endif %}
But it's still loading the data between the if statement.
Any idea what I need to do to load the results on the same page?
Try to simplify this line:
{% if json_data is not none and info is not none %}
to:
{% if json_data and info %}
Here is a worked demo:
view:
app.route('/')
def index():
name = None
age = None
return render_template('index.html', name=name, age=age)
index.html:
{% if name and age %}
Hello, boy!
{% endif %}
I'm new to Flask and I'm trying to run a python script from background upon click on a button in a html page. Here is my code:
from flask import *
from functools import wraps
import sqlite3
app = Flask(__name__)
#app.route('/')
def home():
return render_template('home.html')
#app.route('/generate')
def generate():
return render_template('process.html')
and my process.html is as follows:
<html>
<head>
<body>
Processing...
<script>
exec('python /pth to my python file/myfile.py')
</script>
</body>
</head>
</html>
and home.html is as follows:
{% extends "template.html" %}
{% block content %}
<div class = "jumbo">
<h2> Home</h2>
<br/>
<p>click me</p>
<p> lorem epsum </p>
<div>
{% endblock %}
I'm working on linux and I do not know whether it is possible to use exec in html as shown above. However exec command inside .html file is not executing. I'm still new to flask and I would appreaciate any suggestion on how to make it work.
The <script> tag in HTML is specifically for running client-side JavaScript code. Back-end logic should be done in the views. If you're just looking to execute a line of code that is present in myfile.py, you should put it in a function in that file and import it using from myfile import functionname or simply have that code present in the views (the latter being the proper way to do it in most cases). For example, if myfile.py contained print 'Hello World!' then your views should look like this:
from flask import *
from functools import wraps
import sqlite3
app = Flask(__name__)
#app.route('/')
def home():
return render_template('home.html')
#app.route('/generate')
def generate():
print 'Hello World!'
return render_template('process.html')
If you did it this way, you wouldn't have to split all of your code up into separate files. Unfortunately though, the template would be rendered after the code is executed, so 'Processing...' as shown in your process.html template would display after it has already been processed. As far as Flask goes, the best way that I'm aware of to show the user that the process took place would be to redirect back to the page and flash a message, like this:
#app.route('/generate')
def generate():
print 'Hello World!'
flash('Process complete!')
return redirect(url_for(home))
and then in home.html you would have something like this (from Flask 0.11 Documentation):
{% extends "template.html" %}
{% block content %}
<div class = "jumbo">
<h2> Home</h2>
<br/>
{% with messages = get_flashed_messages() %}
{% if messages %}
<ul class=flashes>
{% for message in messages %}
<li>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
{% endwith %}
<p>click me</p>
<p> lorem epsum </p>
<div>
{% endblock %}
If you wanted something like 'Processing...' to display on the page, that's when you would want to use JavaScript.
Hopefully this helps :)