|
# YT link : https://www.youtube.com/watch?v=0qUWOzc0Mjo |
|
# Github link: https://github.com/AammarTufail/fast_api_tutorial_codanics/blob/main/09_titanic_app_plotly/main.py |
|
|
|
from datetime import datetime, timezone |
|
import logging |
|
|
|
# from fastapi import FastAPI |
|
# from fastapi.responses import HTMLResponse |
|
from sanic import Sanic, html, json as sanic_json |
|
|
|
# import seaborn as sns |
|
|
|
import pandas as pd |
|
import plotly.express as px |
|
from plotly.io import to_html |
|
|
|
# app = FastAPI() # Create a FastAPI instance |
|
app = Sanic("PlotlyTestAPP") # Create a Sanic instance |
|
|
|
|
|
@app.middleware("request") |
|
async def add_start_time(request): |
|
# adding start_time for benchmarking |
|
request.ctx.start_time = datetime.now(timezone.utc) |
|
|
|
|
|
@app.middleware("response") |
|
async def add_spent_time(request, response): |
|
request.ctx.spent_time = datetime.now(timezone.utc) - request.ctx.start_time |
|
|
|
# benchmarking info at the end of the response. |
|
# logging.info is not displayed by sanic server and so logging.warning is used |
|
logging.warning(f"Request to {request.url} took {request.ctx.spent_time}") |
|
|
|
|
|
# Load the Titanic dataset |
|
# df = sns.load_dataset("titanic") |
|
df = pd.read_csv( |
|
"https://raw.githubusercontent.com/mwaskom/seaborn-data/master/titanic.csv" |
|
) |
|
|
|
# Perform a simple data transformation |
|
survival_rate = df.groupby("class")["survived"].mean().reset_index() |
|
|
|
POLTLY_JS_CDN = "https://cdn.plot.ly/plotly-3.0.0.min.js" |
|
|
|
|
|
@app.get("/") |
|
async def root(request): |
|
return sanic_json( |
|
body={"message": "Welcome to the Titanic API, we are learning on codanics.com"} |
|
) |
|
|
|
|
|
@app.get("/survival_rate") |
|
async def get_survival_rate(request): |
|
return sanic_json(body=survival_rate.to_dict(orient="records")) |
|
|
|
|
|
@app.get("/survival_rate_plotly") # , response_class=HTMLResponse) |
|
async def survival_rate_plotly(request): |
|
df["class"] = pd.Categorical(df["class"], ["First", "Second", "Third"]) |
|
df["deck"] = pd.Categorical(df["deck"], list("ABCDEFG")) |
|
# Generate the plot with Plotly |
|
fig = px.bar( |
|
df, |
|
x="class", |
|
y="survived", |
|
color="sex", |
|
title="Survival Rate by Class with Plotly", |
|
) |
|
|
|
# Convert the plot to HTML |
|
plot_div = to_html( |
|
fig, full_html=False, include_plotlyjs=False, config={"displayModeBar": False} |
|
) |
|
|
|
# Create the full HTML document |
|
html_content = f""" |
|
<html> |
|
<head> |
|
<title>Survival Rate by Class (Plotly)</title> |
|
<script src="{POLTLY_JS_CDN}"></script> |
|
</head> |
|
<body> |
|
{plot_div} |
|
</body> |
|
</html> |
|
""" |
|
# return HTMLResponse(content=html_content) |
|
return html(body=html_content) |
|
|
|
|
|
data = { |
|
"country": ["China", "India", "United States", "Indonesia", "Pakistan"], |
|
"population": [1444216107, 1393409038, 332915073, 276361783, 225199937], |
|
} |
|
|
|
|
|
@app.get("/population") # , response_class=HTMLResponse) |
|
async def get_world_population(request): |
|
# Generate a Plotly figure |
|
fig = px.bar(data, x="country", y="population", title="World Population by Country") |
|
|
|
# Convert the figure to HTML |
|
plot_html = to_html( |
|
fig, full_html=False, include_plotlyjs=False, config={"displayModeBar": False} |
|
) |
|
|
|
# Embed the plot in a simple HTML page |
|
html_content = f""" |
|
<html> |
|
<head> |
|
<title>World Population Plot</title> |
|
<script src="{POLTLY_JS_CDN}"></script> |
|
</head> |
|
<body> |
|
{plot_html} |
|
</body> |
|
</html> |
|
""" |
|
# return HTMLResponse(content=html_content) |
|
return html(body=html_content) |