Flask: Request SpaceX Launches Data (Unofficial Repo)
A Python virtual environment helps prevent changes to system Python which would render an OS unstable. For example, if a Python module requires a previous version of a dependency, which system Python also uses, and then changes such an existing dependency to another version, system instability can result. So, a Python virtual environment can help contain Python development within its own sandbox to help prevent it from knocking the swing set over or tilting the merry-go-round. For developers, virtual environments can become a system security measure of sorts.
Below, is an example of virtual environment creation:
user_foo@foo_host:~/Desktop$ python3 -m venv foo
user_foo@foo_host:~/Desktop$ cd foo
user_foo@foo_host:~/Desktop/foo$ ls -l
total 20
drwxrwxr-x 2 user_foo user_foo 4096 Jul 1 10:11 bin
drwxrwxr-x 2 user_foo user_foo 4096 Jul 1 09:30 include
drwxrwxr-x 3 user_foo user_foo 4096 Jul 1 09:30 lib
lrwxrwxrwx 1 user_foo user_foo 3 Jul 1 09:30 lib64 -> lib
-rw-rw-r-- 1 user_foo user_foo 69 Jul 1 10:10 pyvenv.cfg
drwxrwxr-x 3 user_foo user_foo 4096 Jul 1 10:10 share
$ source bin/activate
(foo) user_foo@foo_host:~/Desktop/foo$
export LAUNCHES_DEV_ENV=launches.cfg
python3 launches.py
LAUNCHES_DEV_ENV
sets path to this app's env config file.
DEBUG = True
Flask will indicate which address to load in a web browser. Notice that the debugger was activated based on the instruction in the .cfg
file.
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
* Restarting with stat
* Debugger is active!
* Debugger PIN: XXX-XXX-XXX
Then load http://127.0.0.1:5000/
in a web browser.
launches.py
is a Flask app which imports flask.Flask()
, flask.render_template()
, json.loads()
and requests.get()
modules.
app = Flask(__name__)
instantiates Flask classapp.config.from_envvar('LAUNCHES_DEV_ENV')
sets a specific environmental variable for configuration.@app.route('/')
is a decorator which modifies theindex()
function, and declares a route. Whenever a user loads the root URL/
, theindex()
function is executed.requests.get("https://api.spacexdata.com/v3/launches")
requests a JSON blob from the SpaceX API.data = json.loads(res.text)
assigns the blob to a local variablerender_template("launches.html", data=data)
renders thelaunches.html
template which uses a Jinja2 for loop to iterate through a list of launches
if __name__ == '__main__':
app.run()
The block above has to do with running the app as a standalone module. If this script was imported into another Python app, its __name__
value would be launches
instead of __main__
.
import json
from requests import get
from flask import Flask, render_template
app = Flask(__name__)
app.config.from_envvar('LAUNCHES_DEV_ENV')
@app.route('/')
def index():
res = requests.get("https://api.spacexdata.com/v3/launches")
data = json.loads(res.text)
return render_template("launches.html", data=data)
if __name__ == '__main__':
app.run()
launches.html
is a template which features Jinja2 template engine syntax, e.g. {{ i.mission_name }}
.
{% for i in data %} ... {% endfor %}
iterates the template through a list of launches{{ i.flight_number }}
demos Jinja2 handlebars (or mustache syntax) used to pass values from the SpaceX API to the template.
<!DOCTYPE html>
<html lang="en">
<head>
<title>Launches | SpaceX</title>
<style>
div {
padding: 10px;
margin: 10px;
background-color: #BBFFFF;
box-shadow: 5px 5px 5px #D8D8D8;
}
</style>
</head>
<body>
<h1>Launches | SpaceX</h1>
<hr>
{% for i in data %}
<div>
<h3>{{ i.mission_name }}</h3>
<table>
<tr><td>Mission patch:</td><td><img src="{{ i.links.mission_patch_small }}"></td></tr>
<tr><td>Flight number:</td><td>{{ i.flight_number }} ({{ i.launch_date_local[0:10] }})</td></tr>
<tr><td>Details:</td><td>{{ i.details }}</td></tr>
<tr><td>Launch site:</td><td>{{ i.launch_site.site_name_long }}</td></tr>
</table>
<h3>Rocket</h3>
<table>
<tr><td>Name:</td><td>{{ i.rocket.rocket_name }}</td></tr>
<tr><td>Type:</td><td>{{ i.rocket.rocket_type }}</td></tr>
</table>
<h3>Payload</h3>
<table>
<tr><td>Type:</td><td>{{ i.rocket.second_stage.payloads.0.payload_type }}</td></tr>
<tr><td>ID:</td><td>{{ i.rocket.second_stage.payloads.0.payload_id }}</td></tr>
<tr><td>Customer(s):</td><td>{{ ', '.join(i.rocket.second_stage.payloads.0.customers) }}</td></tr>
<tr><td>Nationality:</td><td>{{ i.rocket.second_stage.payloads.0.nationality }}</td></tr>
<tr><td>Manufacturer:</td><td>{{ i.rocket.second_stage.payloads.0.manufacturer }}</td></tr>
</table>
<h3>Orbit</h3>
<table>
<tr><td>Type:</td><td>{{ i.rocket.second_stage.payloads.0.orbit }}</td></tr>
<tr><td>Ref. sys.:</td><td>{{ i.rocket.second_stage.payloads.0.orbit_params.reference_system }}</td></tr>
<tr><td>Regime:</td><td>{{ i.rocket.second_stage.payloads.0.orbit_params.regime }}</td></tr>
</table>
<h3>Links</h3>
<table>
<tr><td><a href="{{ i.links.video_link }}" target="_blank">Video</a></td></tr>
<tr><td><a href="{{ i.links.flickr_images[0] }}" target="_blank">Image</a></td></tr>
<tr><td><a href="{{ i.links.presskit }}" target="_blank">Presskit [PDF]</a></td></tr>
<tr><td><a href="{{ i.links.article_link }}" target="_blank">Article</a></td></tr>
<tr><td><a href="{{ i.links.wikipedia }}" target="_blank">Wikipedia</a></td></tr>
</table>
</div>
{% endfor %}
</body>
</html>
The following shell script will force debugger activation, and, if a template is modified, it will reload:
export FLASK_APP=launches.py
export FLASK_DEBUG=1
export TEMPLATES_AUTO_RELOAD=1
flask run