For the fastapi project we are going to use Sqlalchemy and postgresql taking some reference from the fastapi documentation.
# create a virtualenv, with any tool: poetry, pipenv, virtualenv module, etc
pip install fastapi uvicorn aiofiles SQLAlchemy psycopg2-binary
project structure
.
├── Dockerfile
├── LICENSE
├── main.py
├── README.md
├── requirements.txt
└── timezone_utils
├── database.py
├── __init__.py
├── models.py
├── schemas.py
└── utils.py
1 directory, 10 files
we define the models, schemas and engine for sqlalchemy and the api in the package timezone_utils
for the query of the timezone using sqlalchemy will be like this:
import sqlalchemy as sa
from sqlalchemy.orm import Session
from . import models, schemas
def get_timezone(db: Session, point: schemas.TimezoneInput) -> schemas.Timezone:
name = db.query(models.Timezones.tzid).filter(
sa.func.ST_Contains(
models.Timezones.geom, sa.func.ST_MakePoint(
point.longitude,
point.latitude)
)
).scalar()
return schemas.Timezone(name=name)
similar to the query in SQL, but using sqlalchemy, for the api the endpoint will accept query parameters for latitude and longitude and return a json with the timezone name.
the endpoint is defined like this:
from fastapi import FastAPI, Depends, Query
from sqlalchemy.orm import Session
from timezone_utils import schemas, models, utils
from timezone_utils.database import engine, SessionLocal
models.Base.metadata.create_all(bind=engine)
tags_metadata = [
{
"name": "timezone",
"description": "Find timezone"
}
]
app = FastAPI(
title="Timezone Lookup",
description="Find timezone name using latitude and longitude",
version="0.0.1",
openapi_tags=tags_metadata
)
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
@app.get("/timezone", response_model=schemas.Timezone, tags=["timezone"])
async def get_timezone(
latitude: float = Query(gt=-85, lt=85, default=0, example=12),
longitude: float = Query(gt=-180, lt=180, default=0, example=-86),
db: Session = Depends(get_db)
):
point = schemas.TimezoneInput(latitude=latitude, longitude=longitude)
return utils.get_timezone(db, point)
Then we can test using curl or the swagger ui from the api documentation.
curl -X GET "http://localhost:8000/timezone?latitude=16&longitude=-86" -H "accept: application/json"
{
"name": "America/Tegucigalpa"
}
This also can be implemented in Go and using a key value db Boltdb go - version
reference: