mirror of
https://github.com/Xevion/trivia.git
synced 2025-12-10 08:08:56 -06:00
overhaul of application structure, added new configs, switched to current_app contextual implementation, proper flask app creation and handling
This commit is contained in:
@@ -1,2 +1,2 @@
|
|||||||
FLASK_APP=wsgi.py
|
FLASK_APP=trivia.create_app
|
||||||
FLASK_ENV=development
|
FLASK_ENV=development
|
||||||
8
setup.py
Normal file
8
setup.py
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
from setuptools import setup
|
||||||
|
|
||||||
|
setup(
|
||||||
|
name='flask-demo',
|
||||||
|
entry_points= {
|
||||||
|
'con'
|
||||||
|
}
|
||||||
|
)
|
||||||
@@ -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
5
trivia/__main__.py
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
from create_app import create_app
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
app = create_app()
|
||||||
|
app.run()
|
||||||
@@ -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
22
trivia/config.py
Normal 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
23
trivia/create_app.py
Normal 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
|
||||||
@@ -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.
|
||||||
|
|||||||
@@ -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 %}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user