overhaul of application structure, added new configs, switched to current_app contextual implementation, proper flask app creation and handling

This commit is contained in:
Xevion
2020-06-20 18:50:46 -05:00
parent 45a49c7c85
commit a2bde58ace
11 changed files with 93 additions and 49 deletions

View File

@@ -1,2 +1,2 @@
FLASK_APP=wsgi.py FLASK_APP=trivia.create_app
FLASK_ENV=development FLASK_ENV=development

8
setup.py Normal file
View File

@@ -0,0 +1,8 @@
from setuptools import setup
setup(
name='flask-demo',
entry_points= {
'con'
}
)

View File

@@ -1,21 +0,0 @@
"""
__init__.py
"""
from collections import namedtuple
from apscheduler.schedulers.background import BackgroundScheduler
from flask import Flask
app = Flask(__name__)
# Simple fake 'class' for passing to jinja templates
Team = namedtuple('Team', ['id', 'name', 'scores'])
from trivia import routes, api, utils
# Setup a scheduler for automatically refreshing data
scheduler = BackgroundScheduler()
scheduler.start()
scheduler.add_job(func=utils.refreshScores, trigger="interval", seconds=5)
utils.refreshScores()

5
trivia/__main__.py Normal file
View File

@@ -0,0 +1,5 @@
from create_app import create_app
if __name__ == '__main__':
app = create_app()
app.run()

View File

@@ -6,13 +6,11 @@ Handles backend routes assisting
import json import json
import time import time
from flask import request, make_response from flask import request, make_response, current_app
from trivia import app
@app.route("/api/scores") @current_app.route("/api/scores")
@app.route("/api/scores/") @current_app.route("/api/scores/")
def scores(): def scores():
""" """
Used for refreshing client-side table data. Returns a JSON response with all data necessary to build the table. Used for refreshing client-side table data. Returns a JSON response with all data necessary to build the table.
@@ -34,6 +32,6 @@ def scores():
except KeyError: except KeyError:
pass # Header was not supplied. Ignore. pass # Header was not supplied. Ignore.
except ValueError: except ValueError:
app.logger.warning('If-Modified-Since Header could not be parsed.') # Header could not be parsed. current_app.logger.warning('If-Modified-Since Header could not be parsed.') # Header could not be parsed.
return r, status_code return r, status_code

22
trivia/config.py Normal file
View File

@@ -0,0 +1,22 @@
"""
config.py
"""
configs = {
'production': 'trivia.config.Config',
'development': 'trivia.config.Config',
'demo': 'trivia.config.DemoConfig'
}
class Config(object):
SCORE_FILE = 'scores.json'
DEMO = False
class DemoConfig(Config):
SCORE_FILE = 'demo.json'
DEMO = True

23
trivia/create_app.py Normal file
View File

@@ -0,0 +1,23 @@
from apscheduler.schedulers.background import BackgroundScheduler
from flask import Flask
from trivia import utils
from trivia.config import configs
def create_app(env=None):
app = Flask(__name__)
if not env:
env = app.config['ENV']
app.config.from_object(configs[env])
# Setup a scheduler for automatically refreshing data
scheduler = BackgroundScheduler()
scheduler.start()
scheduler.add_job(func=utils.refreshScores, trigger="interval", seconds=5)
with app.app_context():
utils.refreshScores()
return app

View File

@@ -3,12 +3,10 @@ routes.py
Handles user frontend routes. Handles user frontend routes.
""" """
from flask import render_template from flask import render_template, current_app
from trivia import app
@app.route("/") @current_app.route("/")
def index(): def index():
""" """
Handles the frontend user index. Handles the frontend user index.

View File

@@ -16,7 +16,8 @@
.fixed_headers th, .fixed_headers th,
.fixed_headers td { .fixed_headers td {
font-family: arial, serif; font-family: Candara, serif;
font-size: large;
font-weight: bold; font-weight: bold;
/*padding: 5px;*/ /*padding: 5px;*/
text-align: left; text-align: left;
@@ -57,6 +58,16 @@
.fixed_headers tbody tr:nth-child(even) { .fixed_headers tbody tr:nth-child(even) {
background-color: #DDD; background-color: #DDD;
} }
th, td > div {
{#width: 100%;#}
height: 10%;
overflow: hidden;
}
th, td {
height: 20px;
}
</style> </style>
</head> </head>
<body> <body>
@@ -64,7 +75,7 @@
<table class="fixed_headers" style="height:100%;width:100%; position: absolute; top: 0; bottom: 0; left: 0; right: 0;"> <table class="fixed_headers" style="height:100%;width:100%; position: absolute; top: 0; bottom: 0; left: 0; right: 0;">
<thead> <thead>
<tr> <tr>
<th>Rank</th> <th style="height: 10%;">Rank</th>
<th>Team Name</th> <th>Team Name</th>
{% for i in range(scoreCount) %} {% for i in range(scoreCount) %}
<th>{{ i + 1 }}</th> <th>{{ i + 1 }}</th>
@@ -73,7 +84,7 @@
</thead> </thead>
<tbody> <tbody>
{% for team in teams %} {% for team in teams %}
<tr> <tr id="{{ team.id }}">
<td>{{ range(1, teams | length) | random }}</td> <td>{{ range(1, teams | length) | random }}</td>
<td>{{ team.name }}</td> <td>{{ team.name }}</td>
{% for score in team.scores %} {% for score in team.scores %}

View File

@@ -5,9 +5,14 @@ Stores important backend application functionality.
""" """
import json import json
import os import os
from collections import namedtuple
from typing import List from typing import List
from trivia import Team, app # Simple fake 'class' for passing to jinja templates
# from trivia import app
from flask import current_app
Team = namedtuple('Team', ['id', 'name', 'scores'])
# Generate paths # Generate paths
BASE_DIR = os.path.dirname(os.path.abspath(__file__)) BASE_DIR = os.path.dirname(os.path.abspath(__file__))
@@ -41,7 +46,7 @@ def refreshScores() -> None:
# Update tracking var # Update tracking var
lastChange = curChange lastChange = curChange
app.logger.debug('Attempting to load and parse scores file.') current_app.logger.debug('Attempting to load and parse scores file.')
with open(SCORES_FILE) as file: with open(SCORES_FILE) as file:
temp = json.load(file) temp = json.load(file)
@@ -53,11 +58,16 @@ def refreshScores() -> None:
scores=team['scores'] scores=team['scores']
) for team in temp ) for team in temp
] ]
app.logger.debug(f'Successfully loaded ({len(temp)} teams).') current_app.logger.debug(f'Successfully loaded ({len(temp)} teams).')
global teams global teams
teams = temp teams = temp
# If invalid or inaccessible, simply do nothing. # If invalid or inaccessible, simply do nothing.
except json.JSONDecodeError: except json.JSONDecodeError:
app.logger.error('Scores file could not be opened or parsed.', print_exc=True) current_app.logger.error('Scores file could not be opened or parsed.', print_exc=True)
def generateDemo() -> None:
pass

10
wsgi.py
View File

@@ -1,10 +0,0 @@
"""
wsgi.py
Simple launcher file for project.
"""
from trivia import app
if __name__ == "__main__":
app.run(host="0.0.0.0", use_reloader=False)