Server-Side Scripting/Strings and Files/Python (FastAPI)

From Wikiversity
Jump to navigation Jump to search

routers/lesson5.py[edit | edit source]

# This program reads a user-selected text file of Fahrenheit
# temperatures and converts the temperatures to Celsius.
#
# File format:
# 32° F
# 98.6° F
# 212° F 
#
# References:
#   https://www.mathsisfun.com/temperature-conversion.html
#   https://fastapi.tiangolo.com/tutorial/request-files/

from fastapi import APIRouter, Request, File, UploadFile
from fastapi.responses import HTMLResponse
from fastapi.templating import Jinja2Templates

router = APIRouter(prefix="/lesson5")
templates = Jinja2Templates(directory="templates")

@router.get("/", response_class=HTMLResponse)
async def get_lesson5(request: Request):
    return templates.TemplateResponse(
        "lesson5.html", 
        {   
            "request": request,
            "table": ""
        }
    )

@router.post("/", response_class=HTMLResponse)
async def post_lesson5(request: Request, file: UploadFile = File(...)):
    try:
        result = await process_file(file)
    except Exception as exception:
        result = exception

    return templates.TemplateResponse(
        "lesson5.html", 
        {   
            "request": request,
            "table": result
        }
    )

async def process_file(file):
    if not file:
        return "No file selected"

    result = f"<h2>{file.filename}</h2>"
    result += "<table><tr><th>Fahrenheit</th><th>Celsius</th></tr>"

    text = await file.read()
    text = text.decode()
    lines = text.strip().split("\n")
    for line in lines:
        result += process_line(line)

    result += "</table>"
    return result

def process_line(line):
    index = line.find("° F")
    if index < 0:
        return "Invalid file format"

    try:
        fahrenheit = float(line[0:index])
    except:
        return "Invalid temperature data"

    celsius = (fahrenheit - 32) * 5 / 9
    result = f"<tr><td>{fahrenheit}</td>"
    result += f"<td>{celsius:.1f}</td></tr>"
    return result

templates/lesson5.html[edit | edit source]

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Lesson 5</title>
    <link rel="stylesheet" href="{{url_for('static', path='/styles.css')}}">
    <style>
        p {
            min-height: 1em;
        }
    </style>
</head>

<body>
    <h1>Temperature Conversion</h1>
    <p>Select a file of Fahrenheit temperatures for conversion:</p>
    <form method="POST" enctype="multipart/form-data">
        <input type="file" id="file" name="file">
        <input type="submit">
    </form>
    {{table|safe}}
</body>

</html>

Try It[edit | edit source]

See Server-Side Scripting/Routes and Templates/Python (FastAPI) to create a test environment.

See Also[edit | edit source]