Add table querying via form

This commit is contained in:
coolneng 2020-01-09 19:13:24 +01:00
parent 6caca22472
commit 1aac68473d
Signed by: coolneng
GPG Key ID: 9893DA236405AF57
12 changed files with 141 additions and 42 deletions

View File

@ -46,6 +46,13 @@ CLOSED: [2019-11-01 Fri 00:34]
- [X] Entity-Relationship - [X] Entity-Relationship
** Implementation ** Implementation
*** TODO Backend [2/4] [50%] *** TODO Backend [2/4] [50%]
**** TODO Flask Application [2/3] [66%]
- [ ] Plots with pandas
- [X] Login for admin
- [X] Tables with pandas
**** TODO Possible additions [1/2] [50%]
- [ ] Text search for glaciers
- [X] Form seach for a year
**** DONE Database [3/3] [100%] **** DONE Database [3/3] [100%]
CLOSED: [2020-01-03 Fri 00:44] CLOSED: [2020-01-03 Fri 00:44]
- [X] Connection - [X] Connection
@ -56,15 +63,12 @@ CLOSED: [2020-01-08 Wed 03:18]
- [X] Select useful fiels - [X] Select useful fiels
- [X] Convert PU to Country (ISO 3166) - [X] Convert PU to Country (ISO 3166)
- [X] Insert into database - [X] Insert into database
**** TODO Flask Application [1/4] [25%] *** TODO Documentation [0/2] [0%]
- [ ] Arithmetic operations for yearly changes - [ ] Code
- [ ] Tables with pandas - [ ] Explanations (uid as Varchar, ORM)
- [ ] Plots with pandas *** TODO Deployment [0/1] [0%]
- [X] Login for admin - [ ] Virtualenv installation script
**** TODO Possible additions [0/2] [0%] *** DONE Frontend [2/2] [100%]
- [ ] Text search for glaciers CLOSED: [2020-01-09 Thu 11:09]
- [ ] Form seach for a year
*** TODO Frontend [1/2] [50%]
- [X] Flask-Bootstrap - [X] Flask-Bootstrap
- [ ] Find CSS - [X] Find CSS
*** TODO Documentation

View File

@ -1,5 +1,5 @@
from flask_wtf import FlaskForm from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, BooleanField, SubmitField from wtforms import BooleanField, PasswordField, SelectField, StringField, SubmitField
from wtforms.validators import DataRequired from wtforms.validators import DataRequired
@ -8,3 +8,39 @@ class LoginForm(FlaskForm):
password = PasswordField("Password", validators=[DataRequired()]) password = PasswordField("Password", validators=[DataRequired()])
remember_me = BooleanField("Remember Me") remember_me = BooleanField("Remember Me")
submit = SubmitField("Sign In") submit = SubmitField("Sign In")
class YearForm(FlaskForm):
year_list = [
("2011", 2011),
("2012", 2012),
("2013", 2013),
("2014", 2014),
("2015", 2015),
("2016", 2016),
("2017", 2017),
("2018", 2018),
]
year = SelectField("Year", validators=[DataRequired()], choices=year_list)
submit = SubmitField("Search")
class IntervalForm(FlaskForm):
year_list = [
("2011", 2011),
("2012", 2012),
("2013", 2013),
("2014", 2014),
("2015", 2015),
("2016", 2016),
("2017", 2017),
("2018", 2018),
]
name = StringField("Glacier Name")
lower_bound = SelectField(
"First year", validators=[DataRequired()], choices=year_list
)
upper_bound = SelectField(
"Second year", validators=[DataRequired()], choices=year_list
)
submit = SubmitField("Search")

View File

@ -1,9 +1,10 @@
from app import app from app import app, db
from app.forms import LoginForm from app.forms import LoginForm, YearForm, IntervalForm
from app.models import User from app.models import User, Annual_Data, Glacier
from flask import flash, redirect, render_template, url_for, request from flask import flash, redirect, render_template, url_for, request
from flask_login import current_user, login_user, logout_user, login_required from flask_login import current_user, login_user, logout_user, login_required
from werkzeug.urls import url_parse from werkzeug.urls import url_parse
from processing.tabulate import create_table
@app.route("/") @app.route("/")
@ -53,9 +54,24 @@ def data():
return render_template("data.html", title="Data") return render_template("data.html", title="Data")
@app.route("/tables") @app.route("/table_selection", methods=["GET", "POST"])
def tables(): def table_selection():
return render_template("data.html", title="Data") form = YearForm()
if form.validate_on_submit():
annual_data = (
db.session.query(Annual_Data).filter_by(year=form.year.data).statement
)
if annual_data is None:
flash("Invalid query, please try again")
return redirect(url_for("table_selection"))
table = create_table(annual_data)
return render_template("table.html", table=table, title="Table")
return render_template("table_selection.html", title="Data", form=form)
@app.route("/table")
def table():
return render_template("table.html", table=table, title="Table")
@app.route("/plots") @app.route("/plots")

View File

@ -1,7 +1,16 @@
{% extends "base.html" %} {% extends "base.html" %}
{% block content %} {% block content %}
<h1>Hey, {{ current_user.username }}!</h1> <h1 class="text-center">Hey, {{ current_user.username }}!</h1>
Do you want to nuke the database? <p class="text-center">Do you want to nuke the database?</p>
<li><a href="{{ url_for('nuke') }}">Yes, I want to burn down the world</a></li> <li>
<p class="text-center">
<a href="{{ url_for('nuke') }}"><b>Yes</b>, I want to burn down the world</a>
</p>
</li>
<li>
<p class="text-center">
Nah, show me some cool <a href="{{ url_for('data') }}">data</a>
</p>
</li>
{% endblock %} {% endblock %}

View File

@ -1,7 +1,7 @@
{% extends 'bootstrap/base.html' %} {% extends 'bootstrap/base.html' %}
{% block title %} {% block title %}
IGDB {% if title %}{{ title }} - IGDB{% else %}IGDB{% endif %}
{% endblock %} {% endblock %}
{% block styles %} {% block styles %}

View File

@ -1,8 +1,15 @@
{% extends "base.html" %} {% extends "base.html" %}
{% block content %} {% block content %}
<h1>Hey, {{ current_user.username }}!</h1> <h1 class="text-center">What do you want to check out?</h1>
Wanna check out some cool data? <li>
<li><a href="{{ url_for('tables') }}"></a></li> <p class="text-center">
<li><a href="{{ url_for('plots') }}"></a></li> <a href="{{ url_for('table_selection') }}">Tables</a>
</p>
</li>
<li>
<p class="text-center">
<a href="{{ url_for('plots') }}">Plots</a>
</p>
</li>
{% endblock %} {% endblock %}

View File

@ -0,0 +1,7 @@
{% extends "base.html" %}
{% import 'bootstrap/wtf.html' as wtf %}
{% block app_content %}
<h1>Table</h1>
{{ table|safe }}
{% endblock %}

View File

@ -0,0 +1,12 @@
{% extends "base.html" %}
{% import 'bootstrap/wtf.html' as wtf %}
{% block app_content %}
<h1>Table selection</h1>
<div class="row">
<div class="col-md-4">
{{ wtf.quick_form(form) }}
</div>
</div>
<br>
{% endblock %}

View File

@ -1,19 +1,9 @@
from app import db
from app.models import Annual_Data, Glacier, User from app.models import Annual_Data, Glacier, User
from database.constants import DB_NAME, DB_PW, DB_USER
from pandas import DataFrame, read_csv from pandas import DataFrame, read_csv
from sqlalchemy import create_engine, engine
def create_connection() -> engine: def create_dataframes() -> {DataFrame}:
host = "localhost:3306"
connection_uri = "mysql+pymysql://{user}:{pw}@{url}/{db}".format(
user=DB_USER, pw=DB_PW, url=host, db=DB_NAME
)
engine = create_engine(connection_uri)
return engine
def create_dataframes() -> DataFrame:
files = { files = {
"glacier": "../data/glacier.csv", "glacier": "../data/glacier.csv",
"annual_data": "../data/annual_data.csv", "annual_data": "../data/annual_data.csv",
@ -25,19 +15,18 @@ def create_dataframes() -> DataFrame:
return df_list return df_list
def insert_data(df_list, conn): def insert_data(df_list):
models = [Glacier, Annual_Data, User] models = [Glacier, Annual_Data, User]
for model in models: for model in models:
if model.query.first() is not None: if model.query.first() is not None:
return return
for key, value in df_list.items(): for key, value in df_list.items():
value.to_sql(key, con=conn, index=False, if_exists="append") value.to_sql(key, con=db.engine, index=False, if_exists="append")
def main(): def main():
conn = create_connection()
df_list = create_dataframes() df_list = create_dataframes()
insert_data(df_list, conn) insert_data(df_list)
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -1,5 +1,6 @@
from app import app from app import app
from database import db_setup, export, parser from database import db_setup, export, parser
from processing import tabulate
db_setup.main() db_setup.main()
parser.main() parser.main()

View File

View File

@ -0,0 +1,18 @@
from app import db
from pandas import DataFrame, read_sql, wide_to_long
def create_dataframe(query) -> DataFrame:
df = read_sql(sql=query, con=db.engine)
return df
def render_table(df) -> str:
table = df.to_html(classes=["table-bordered", "table-striped", "table-hover"])
return table
def create_table(query) -> str:
df = create_dataframe(query)
html_table = render_table(df)
return html_table