Reputation: 33
I've seen similar questions, but most dealing with input forms and GET/POST methods. I'm still learning, and don't know if I need those or not, but looking to pass a created dataset in my Flask main.py file to a later html.
example main.py:
from flask import Flask,render_template
app = Flask(__name__)
#some other sites to test my html learnings between
import requests,re,pandas as pd
url = "https://www.pgatour.com/stats/stat.186.html"
r=requests.get(url)
df_list=pd.read_html(r.text)
df=df_list[1]
wgrank=df.rename(columns={"RANK\xa0THIS WEEK":"Rank","PLAYER NAME":"Name"})
@app.route('/WGRankings')
def WGRankings():
return render_template('WGRankings.html',data=wgrank)
if __name__ == "__main__":
app.run(debug=True)
example WGRankings.html:
<!DOCTYPE html>
<html lang="en" dir="ltr">
<body>
<ul>
{% for item in data: %}
<li>{{item.Rank}}</li>
<li>{{item.Name}}</li>
{% endfor %}
{data} {{data}} {wgrank} {{wgrank}}
</ul>
</body>
and finally the output.
I've tried a few different iterations of this, including pyfetch, but pyfetch doesnt like requests.get(). Any advice and/or documentation to find why I'm struggling to successfully pass a dataset to the html script?
The end goal would be to have a dynamic list that refreshes so you can choose a golfer based on their ranking which changes weekly. There's 1,000 ranked golfers so a hardcoded list doesnt make sense.
Upvotes: 0
Views: 598
Reputation: 8542
If I understand your question correctly, you want to display the golfer rankings within an HTML table at the time of the request.
So you get the data from the website and extract the table with the statistics. You can then rename columns and extract the ones you want to display. Now you pass the entire resulting DataFrame to the template.
All this takes place within the endpoint to constantly receive the updated data.
from flask import (
Flask,
render_template
)
import pandas as pd
import requests
app = Flask(__name__)
@app.route('/ranking')
def ranking():
# Obtain the data and extract the table.
resp = requests.get('https://www.pgatour.com/stats/stat.186.html')
df = pd.read_html(resp.content)[1]
# Rename the specified columns and extract them into a new DataFrame.
data = df.rename(columns={"RANK\xa0THIS WEEK":"Rank","PLAYER NAME":"Name"})[['Rank', 'Name']]
# Pass all local variables to the template by name.
return render_template('ranking.html', **locals())
Within the template you can now iterate over the columns to create the table header and iterate over the rows to create the data body of the table. Each row now contains the cells with the data.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Ranking</title>
</head>
<body>
<table>
<thead>
<tr>
<!-- Iterate over the columns and output their names as header columns. -->
{% for column in data.columns -%}
<th>{{ column }}</th>
{% endfor -%}
</tr>
</thead>
<tbody>
<!-- Iterate over the rows of data. -->
{% for row in data.values -%}
<tr>
<!-- Iterate over the columns of the respective row and output them. -->
{% for cell in row %}
<td>{{ cell }}</td>
{% endfor -%}
</tr>
{% endfor -%}
</tbody>
</table>
</body>
</html>
A standard browser request corresponds to a GET request. This can also be used to send data to the server. In this case, the individual key-value pairs are appended to the URL, after a question mark.
http://localhost:5000/path/to/route?key0=value0&key1=value1
For example, if you want to make a search query, this is usually sufficient. However, in most cases, a POST request is used when sending data to the server. This means that the data is sent in the request body and should normally not be visible to third parties.
Let's say you want to filter the golfer rankings by name that you submit in a search query, you add a form to your template that will be submitted using the GET method, since nothing else was specified using the method
attribute.
<form>
<input type="text" name="q" autocomplete="off" spellcheck="false" value="{{ q or '' }}" />
</form>
On the server you now use request.args.get('...')
to request the value of the input field based on the name. If an entry has been made, you can examine a column of the DataFrame to see whether this entry is contained and filter out these lines. For example, only ranked golfers whose names contain the string you enter will be displayed.
from flask import request
@app.route('/ranking')
def ranking():
q = request.args.get('q')
resp = requests.get('https://www.pgatour.com/stats/stat.186.html')
df = pd.read_html(resp.content)[1]
data = df.rename(columns={"RANK\xa0THIS WEEK":"Rank","PLAYER NAME":"Name"})[['Rank', 'Name']]
if q:
data = data[data['Name'].str.contains(q)]
return render_template('ranking.html', **locals())
Upvotes: 1