Jump to content

Server-Side Scripting/Document Databases/Python (FastAPI)

From Wikiversity

routers/lesson10.py

[edit | edit source]
# This program creates and displays a temperature database
# with options to insert, update, and delete records.
#
# References:
#   https://en.wikibooks.org/wiki/Python_Programming
#   https://docs.mongodb.com/manual/tutorial/
#   https://www.w3schools.com/python/python_mongodb_getstarted.asp

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

import pymongo

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

# Requires a Mongo installation to manage the database.
# Use of a Docker container is recommended.
# See https://en.wikiversity.org/wiki/Docker/MongoDB .
# If both the FastAPI website and Mongo are running in containers, 
# use 172.17.0.2 for the mongodb host address.
# If the FastAPI website and/or Mongo are running locally, use 127.0.0.1
# for the mongodb host address.

# const HOST = "mongodb://172.17.0.2";
HOST = "mongodb://localhost"
DATABASE = "temperature"
COLLECTION = "countries"

@router.get("/", response_class=HTMLResponse)
async def get_lesson10(request: Request):
    try:
        result = get_data()
    except Exception as exception:
        result = exception

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

@router.post("/", response_class=HTMLResponse)
async def post_lesson10(request: Request):
    form = dict(await request.form())
    try:
        country = form["country"].strip()
        temperature = form["temperature"].strip()

        if not country_exists(country):
            insert_country(country, temperature)
        elif temperature != "":
            update_country(country, temperature)
        else:
            delete_country(country)

        result = get_data()
    except Exception as exception:
        result = exception

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

def get_data():
    mongo = pymongo.MongoClient(HOST)
    database = mongo[DATABASE]
    collection = database[COLLECTION]
    result = "<table><tr><th>ID</th>"
    result += "<th>Country</th>"
    result += "<th>Temperature</th></tr>"
    for document in collection.find():
        result += f"<tr><td>{document['_id']}</td>"
        result += f"<td>{document['country']}</td>"
        result += f"<td>{document['temperature']}</td></tr>"
    result += "</table>"
    return result

def country_exists(country):
    mongo = pymongo.MongoClient(HOST)
    database = mongo[DATABASE]
    collection = database[COLLECTION]
    filter = {
        "country": country
    }
    return bool(collection.count(filter))

def insert_country(country, temperature):
    mongo = pymongo.MongoClient(HOST)
    database = mongo[DATABASE]
    collection = database[COLLECTION]
    document = {
        "country": country,
        "temperature": temperature
    }
    collection.insert_one(document)

def update_country(country, temperature):
    mongo = pymongo.MongoClient(HOST)
    database = mongo[DATABASE]
    collection = database[COLLECTION]
    filter = {
        "country": country
    }
    update = {
        "$set": { "temperature": temperature }
    }
    collection.update_one(filter, update)

def delete_country(country):
    mongo = pymongo.MongoClient(HOST)
    database = mongo[DATABASE]
    collection = database[COLLECTION]
    filter = {
        "country": country
    }
    collection.delete_one(filter)

templates/lesson10.html

[edit | edit source]
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Lesson 10</title>
    <link rel="stylesheet" href="{{url_for('static', path='/styles.css')}}">
</head>

<body>
    <h1>Temperature Data Entry</h1>
    <p>Enter country and temperature. Enter again to update.</p>
    <p>Enter country without temperature to delete.</p>
    <form method="POST">
        <p><label for="country">Country:</label>
            <input type="text" id="country" name="country" required>
        </p>
        <p><label for="stop">Temperature:</label>
            <input type="text" id="temperature" name="temperature">
        </p>
        <p><input type="submit" name="submit" value="Submit"></p>
    </form>
    <hr>
    {{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]