I am trying to display some simple 3 day weather forecast data using pythonanywhere flask app. Here is my code so far:
from flask import Flask, render_template
import requests
from collections import defaultdict
app = Flask(__name__)
r = requests.get("http://api.wunderground.com/api/mykey/forecast/q/SouthAFrica/Stellenbosch.json")
data = r.json()
weather_data = defaultdict(list)
counter = 0
for day in data['forecast']['simpleforecast']['forecastday']:
date= day['date']['weekday'] + ":"
cond= "Conditions: ", day['conditions']
temp= "High: ", day['high']['celsius'] + "C", "Low: ", day['low']['celsius'] + "C"
counter = counter + 1
weather_data[counter].append(date)
weather_data[counter].append(cond)
weather_data[counter].append(temp)
return weather_data
#app.route('/')
def home():
return render_template('home.html', weather_data=weather_data)
if __name__ == '__main__':
app.run(host="0.0.0.0", port=5000)
and here is the simple 'home.html':
<table>
{% for key,value in weather_data.items() %}
<tr>
<td>{{value[1]}}</td>
<td>{{value[2]}}</td>
<td>{{value[3]}}</td>
<td>{{value[4]}}</td>
</tr>
{% endfor %}
</table>
I can't seem to get this to work. I suspect it is something to do with the format of the data? Should it rather be a separate file that is imported?
Put the python logic within your view function, like this:
#app.route('/')
def home():
r = requests.get("http://api.wunderground.com/api/key/forecast/q/SouthAfrica/Stellenbosch.json")
data = r.json()
weather_data = defaultdict(list)
counter = 0
for day in data['forecast']['simpleforecast']['forecastday']:
date = day['date']['weekday'] + ":"
cond = "Conditions: ", day['conditions']
temp = "High: ", day['high']['celsius'] + "C", "Low: ", day['low']['celsius'] + "C"
counter += 1
weather_data[counter].append(date)
weather_data[counter].append(cond)
weather_data[counter].append(temp)
return render_template('home.html', weather_data=weather_data)
By looking at the API data I think your {{ value[1] }} is still a tuple so you might need something like {{ value[1][0] }}, {{ value[1][1] }} in your template to render this data.
Add print statements to your python to debug how to parse the data structure.
Related
I have this code that is in python and randomly makes a math equation and checks the user answer for 1 minute:
import random
import time
correct=0
wrong=0
def random_problem(num_operations):
eq = str(random.randint(1, 100))
for _ in range(num_operations):
eq += random.choice(["+"])
eq += str(random.randint(1, 100))
return eq
start = time.time()
while True:
elapsed = time.time() - start
if elapsed > 60:
quotient=correct/wrong
precent=quotient*10
total_questions=correct+wrong
print(correct,"Correct",wrong,"Wrong, total questions",total_questions)
break
problem = random_problem(1)
ask=int(input(problem +": "))
solution = eval(problem)
if ask == solution:
correct=correct+1
print("Correct")
else:
wrong=wrong+1
print("Wrong, the correct answer is",solution)
I wanted to know if it is possible to make this go from the console onto a UI. I and using flask. Thanks
Flask server is good for this. This is how the code in the flask should look like:
# app.route('/', methods=['GET', 'POST'])
def home():
if request.method == "POST":
num = request.form['num']
# Check num if it is correct, use your code
# result is the data you will want to save
open_file('data.json', "w", result)
# math is your example
return render_template("index.html", math=math)
To save, I used my open_file () function, which looks like this:
def open_file(name, mode="r", data=None):
script_dir = os.path.dirname(__file__)
file_path = os.path.join(script_dir, name)
if mode == "r":
with open(file_path, mode, encoding='utf-8') as f:
data = json.load(f)
return data
elif mode == "w":
with open(file_path, mode, encoding='utf-8') as f:
json.dump(data, f)
In html, the input form should look like this:
<form method = "POST" >
<input name = "text" type = "text">
<input name = "num" type = "number">
<button> submit </button>
</form>
Your math example show like this:
<h1>{{math}}</h1>
I would probably recommend making a timer on the web in javascript, I think in flask it might not work
I used everything from my github repository: https://github.com/adammaly004/Online_fridge
I hope it will help you, Adam
It's a little hard to understand what you mean by saving the data. There are several different ways to store data. The variant to choose depends on the data and its use.
You can find data from a form in Flask in the request.form object as long as it was sent using the POST method. The name attribute of the input field determines under which you can request the data on the server.
The example below shows you a possible solution how to implement your code in Flask. It should serve as a starting point for you to develop your own solution or expand it on your own.
To avoid the eval function, a dict is used and filled with the necessary operators and functions from the operator module. The result of the generated task is then calculated and saved in the session cookie.
If the user enters a result or lets the time elapse, the input is compared with the result from the session.
The time limit is set by a JavaScript timeout, which automatically submits the form as soon as the time has elapsed.
Flask (app.py)
from flask import Flask
from flask import render_template, request, session
from operator import add, sub
import random
app = Flask(__name__)
app.secret_key = 'your secret here'
#app.route('/', methods=['GET', 'POST'])
def index():
if request.method == 'POST':
# Get the user input and convert it to an integer.
# If no entry is made, the default value 0 is returned.
r = request.form.get('r', 0, type=int)
# Check the result and choose a message depending on it.
msg = (
'Ooops, wrong result.',
'Yeah, you are right.'
)[int(r == session.get('r'))]
# This is the mapping of the operators to the associated function.
ops = { '+': add, '-': sub }
# Generate the task and save the result in the session.
op = random.choice(list(ops.keys()))
a = random.randint(1,100)
b = random.randint(1,100)
session['r'] = ops[op](a,b)
# Render the page and deliver it.
return render_template('index.html', **locals())
HTML (templates/index.html)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Index</title>
</head>
<body>
{% if msg -%}
<p>{{msg}}</p>
{% endif -%}
<form name="task" method="post">
<span>{{a}} {{op}} {{b}} = </span>
<input type="number" name="r" />
<input type="submit">
</form>
<script type="text/javascript">
(function() {
// Submit the form automatically after the time has elapsed.
setTimeout(function() {
document.querySelector('form[name="task"]').submit();
}, 10000)
})();
</script>
</body>
</html>
'''
app.py
from flask import Flask, render_template, request
from weather_backend import temperature_condition,clothes,feels_temperature,weather_description
app = Flask(__name__)
app.config["SECRET_KEY"] = "Secret-key"
#app.route("/")
def index():
return render_template("index.html")
#app.route("/dress")
def dress():
cityname = request.form.get("city_name")
temp = str(temperature_condition())
message = str(clothes())
feels = feels_temperature
description= weather_description
return render_template("dress.html", message=message, temp=temp, feels_temperature=feels,
weather_description=description )
if __name__ == "__main__":
app.run(debug=True)
'''
'''
weather_backend.py
import requests, json
import weatherMappingMessage
from app import dress
from keys import *
base_url = "http://api.openweathermap.org/data/2.5/weather?"
city_name =
complete_url = base_url + "appid=" + api_key + "&q=" + city_name + "&units=metric"
response = requests.get(complete_url)
'''
HTML file
'''
<body>
<div class="head">
<form action= "{{ url_for('dress') }}" class="form" method="GET">
<h1>Get Weather and Dresses according to the Weather</h1>
<div class = "form-box">
<input type="text" class="search-field location" name= "city_name" placeholder="Location...">
<button class="search-btn" type="button">Search</button>
</div>
</form>
</div>
</body>
'''
I need to get the form info(search) from HTML to the backend(city_name) and then to the flask(cityname)
I can get a message from the backend if try to get it but I can't get HTML form to the backend for processing
The problem I'm facing is that I can't get the form data from my HTML file to my backend for processing
basically, I need the cityname to the backend for getting my weather description
Short answer:
Because your form submission uses a get request, you can use request.args to get parsed contents of query string (see also):
cityname = request.args.get("city_name")
Long answer:
I'm sure you're asking for more than just this piece of code. I took the code you provided and added the missing pieces in-line (please don't do this for production code) and also passed cityname to render_template:
import logging
from datetime import datetime
from flask import render_template, request
from app import app, forms
#app.route("/")
def index():
return render_template("index.html")
#app.route("/dress")
def dress():
cityname = request.args.get("city_name")
# missing in example code
def temperature_condition():
return 'temp cond'
# missing in example code
def clothes():
return 'clothes'
feels_temperature = 'feels temp' # missing in example code
weather_description = 'weather desc' # missing in example code
temp = str(temperature_condition())
message = str(clothes())
feels = feels_temperature
description = weather_description
return render_template("dress.html", message=message, temp=temp, feels_temperature=feels,
weather_description=description, cityname=cityname) # also pass cityname
I created a minimalistic dress.html:
<html>
<body>
<p>message = {{ message }}</p>
<p>temp = {{ temp }}</p>
<p>feels_temperature = {{ feels_temperature }}</p>
<p>weather_description = {{ weather_description }}</p>
<p>cityname = {{ cityname }}</p>
</body>
</html>
Starting the application via flask run allows me to input a city name into the form field and view the results (for example 'Berlin'):
In order to show the weather description for the chosen city, you could create a function that accepts the city name and retrieves the information from the web (just a rough sketch):
import requests, json
import weatherMappingMessage
from app import dress
from keys import *
def weather_for_city(city_name):
base_url = "http://api.openweathermap.org/data/2.5/weather?"
complete_url = base_url + "appid=" + api_key + "&q=" + city_name + "&units=metric"
response = requests.get(complete_url)
if response.status_code == 200:
return response.json() # assumes your API returns a JSON response
else:
# perform some error handling here, maybe apply a retry strategy
pass
Extract the relevant data from the result of weather_for_city and pass it to render_template like you did for the other variables.
This question already has answers here:
Are global variables thread-safe in Flask? How do I share data between requests?
(4 answers)
Store large data or a service connection per Flask session
(1 answer)
Closed 2 years ago.
I am taking input(city name) from the user using a form and using the input(city name) I am fetching a real time weather data after some pre processing a 'sample' numpy variable is created and I am trying to use 'sample' in a different funtion to display the output on a different page.
Here is the app.py code:
from flask import Flask, request, jsonify, render_template
import requests
import math
import numpy as np
import pickle
app = Flask(__name__)
modelMLR = pickle.load(open('modelMLR.pkl','rb'))
#app.route('/')
def home():
return render_template('main.html')
#app.route('/algos', methods = ['GET','POST'])
def algos():
city = request.form['location']
api_address = "https://api.openweathermap.org/data/2.5/weather?appid=33a306ae5533eae0fe34e94953cde0a7&q="
url = api_address+city
json_data = requests.get(url).json()
#for Multiple linear Regression
L1=[]
#temperature
kelvin_temp = json_data["main"]["temp_min"]
celcisus_temp = kelvin_temp - 273.15
fahrenheit_temp = celcisus_temp * ( 9 / 5 ) + 32
formatted_data1 = math.floor(fahrenheit_temp)
L1.append(formatted_data1)
kelvin_temp = json_data["main"]["temp_max"]
celcisus_temp = kelvin_temp - 273.15
fahrenheit_temp = celcisus_temp * ( 9 / 5 ) + 32
formatted_data2 = math.floor(fahrenheit_temp)
L1.append(formatted_data2)
#Humidity
L1.append(80)
formatted_data4 = json_data["main"]["humidity"]
L1.append(formatted_data4)
#sea level pressure
L1.append(990)
L1.append(1010)
formatted_data5 = json_data["main"]["pressure"]
L1.append(formatted_data5)
#cloud cover
formatted_data6 = json_data["clouds"]["all"]
L1.append(formatted_data6)
L1.append(formatted_data6)
L1.append(formatted_data6)
L1.append(formatted_data6)
#shortwave radiation
L1.append(0)
#wind speed
L1.append(0)
formatted_data7 = json_data["wind"]["speed"]
L1.append(formatted_data7)
#wind gust
L1.append(0)
L1.append(0)
sample = np.array(L1)
sample= sample.reshape(1, -1)
return render_template("algos.html")
#app.route('/MLR')
def predict_MLR():
prediction = modelMLR.predict(sample)
return render_template('MLR.html', prediction_text = "The current precipitation is: {}".format(prediction))
if __name__ == "__main__":
app.run(debug = False)
I want to use variable 'sample' of algos() function in predict_MLR() function so that I can predict the output and display it on MLR.html page.
main.html:
<!doctype html>
<body>
<h1> Rainfall prediction.. </h1><br>
<form method = "POST" action="{{url_for('algos')}}">
<button type="button"><img width="13px" height="13px" src="back.jpg"></button>
<input type = "text" placeholder="Search for your city.." style="width:300px" name = "location">
<button type = "submit" value="submit"><img src = "search.png" height="13px" width="13px"></button>
</form>
</body>
</html>
algos.html:
<!doctype html>
<html>
<body>
<h1> Rainfall prediction.. </h1><br>
<h1>Multiple Linear Regression<h1>
</body>
</html>
MLR.html:
<!doctype html>
<html>
<h1> Rainfall prediction.. </h1><br>
<h2>{{prediction_text}}</h2>
</html>
A simpler way to write this would be to first define the agios function which returns sample:
def algos(city):
api_address = "https://api.openweathermap.org/data/2.5/weather?appid=33a306ae5533eae0fe34e94953cde0a7&q="
url = api_address+city
json_data = requests.get(url).json()
#for Multiple linear Regression
L1=[]
#temperature
kelvin_temp = json_data["main"]["temp_min"]
celcisus_temp = kelvin_temp - 273.15
fahrenheit_temp = celcisus_temp * ( 9 / 5 ) + 32
formatted_data1 = math.floor(fahrenheit_temp)
L1.append(formatted_data1)
kelvin_temp = json_data["main"]["temp_max"]
celcisus_temp = kelvin_temp - 273.15
fahrenheit_temp = celcisus_temp * ( 9 / 5 ) + 32
formatted_data2 = math.floor(fahrenheit_temp)
L1.append(formatted_data2)
#Humidity
L1.append(80)
formatted_data4 = json_data["main"]["humidity"]
L1.append(formatted_data4)
#sea level pressure
L1.append(990)
L1.append(1010)
formatted_data5 = json_data["main"]["pressure"]
L1.append(formatted_data5)
#cloud cover
formatted_data6 = json_data["clouds"]["all"]
L1.append(formatted_data6)
L1.append(formatted_data6)
L1.append(formatted_data6)
L1.append(formatted_data6)
#shortwave radiation
L1.append(0)
#wind speed
L1.append(0)
formatted_data7 = json_data["wind"]["speed"]
L1.append(formatted_data7)
#wind gust
L1.append(0)
L1.append(0)
sample = np.array(L1)
sample= sample.reshape(1, -1)
return sample
Then have a single route which returns a different result based on the request.method:
#app.route('/')
def home():
if request.method == 'POST':
city = request.form['location']
sample = algos(city)
prediction = modelMLR.predict(sample)
return render_template('main.html', prediction_text = "The current precipitation is: {}".format(prediction))
else:
# GET request, just render the home page
return render_tempate('main.html')
if __name__ == "__main__":
app.run(debug = False)
Notice that prediction_text is only passed through in the event of a POST request.
Now just define a template which handles this case with an if clause:
<!doctype html>
<body>
<h1> Rainfall prediction.. </h1><br>
<form method = "POST" action="{{url_for('home')}}">
<button type="button"><img width="13px" height="13px" src="back.jpg"></button>
<input type = "text" placeholder="Search for your city.." style="width:300px" name = "location">
<input type = "submit" value="submit" />
</form>
{% if prediction_text %}
<h1> Rainfall prediction.. </h1><br>
<h2>{{prediction_text}}</h2>
{% endif %}
</body>
</html>
In the event that you hit the / endpoint with a GET request, the prediction is not shown.
I am trying to get user's input and return the details as json.
But I get an error and I can't find why.
Hers is my python code:
from flask import Flask, request, render_template,jsonify
import json
#app.route('/user_input')
def user_input():
return render_template('user-input.html')
#app.route('/user_input',methods = ['POST'])
def result():
NAME = request.form['Book_Name']
PAGE = request.form['Page']
TEXT = request.form['Text']
TOPIC = request.form['Topic']
pythonDictionary = {'bookName': NAME, 'page': PAGE, 'text': TEXT, 'topic': TOPIC}
dictionaryToJson = json.dumps(pythonDictionary)
return jsonify(dictionaryToJson)
and my HTML file:
<html>
<body>
<form action = "http://localhost:5000/result" method = "POST">
<p>Book Name <input type = "text" name = "Book_Name" /></p>
<p>Page <input type = "text" name = "Page" /></p>
<p>Text <input type = "text" name = "Text" /></p>
<p>Topic <input type ="text" name = "Topic" /></p>
<p><input type = "submit" value = "submit" /></p>
</form>
</body>
</html>
How can I return the values properly?
You are dumping the dict twice as jsonify also does json.dumps() (it also sets the correct response headers for you in addition which is why you should use it instead of json.dumps():
dictionaryToJson = json.dumps(pythonDictionary)
return jsonify(dictionaryToJson)
Do this:
from flask import Flask, request, render_template,jsonify
import json
#app.route('/user_input')
def user_input():
return render_template('user-input.html')
#app.route('/user_input',methods = ['POST'])
def result():
NAME = request.form['Book_Name']
PAGE = request.form['Page']
TEXT = request.form['Text']
TOPIC = request.form['Topic']
pythonDictionary = {'bookName': NAME, 'page': PAGE, 'text': TEXT, 'topic': TOPIC}
return jsonify(pythonDictionary )
0) Do not use uppercase for vars. Uppercase is always for constants.
1) Use routes with "/" at the end to avoid additional redirects which flask does:
#app.route('/user_input/', methods = ['POST'])
2) Use the same route and the same function to get what you need:
from flask import Flask, request, render_template, jsonify
def json_response(status_code, data):
res = jsonify(data)
res.status_code = status_code
return res
app = Flask(__name__)
#app.route('/user_input/', methods=["GET", "POST"])
def user_input():
if request.method == "GET":
return render_template('user-input.html')
else:
python_dictionary = {'bookName': request.form.get('Book_Name'),
'page': request.form.get('Page'),
'text': request.form.get('Text'),
'topic': request.form.get('Topic')}
return json_response(200, python_dictionary)
app.run()
3) And yes, you don't need to use json.dumps(pythonDictionary) before passing dictionary to jsonify
4) Consider to use request.form.get('key') rather than request.form['key'] because get() function returns None if there is no such key:value instead of raising key error exception.
I have a Python/Flask app that gathers data from third-party APIs and stores them in a JSON-like structure (nested Python dictionaries called 'results').
I'm sending this to my template using:
def format_results():
item_data = {'name':name, 'age':age, 'address':address}
results = {'title':item_title, 'item_data':item_data}
return jsonify(results)
#app.route('/')
def display_results():
data = format_results()
return render_template('index.html', data = data)
I would like to use d3.js in my template to plot the results on a graph.
What's the recommended way for doing so? (disclaimer: this is my first time using D3.js)
Figured out a way to make this work!
def format_results():
item_data = {'name':name, 'age':age, 'address':address}
results = {'title':item_title, 'item_data':item_data}
return results
#app.route('/')
def display_results():
data = format_results()
return render_template('index.html', data = data)
Removed 'jsonify' and disabled escaping for {{data}}
de = {% autoescape false %} {{data}} {% endautoescape %}