Creating an API has not been this much easier. In the tutorial, we will use FASTAPI to create a simple API but first what the heck is an API and what terms are we to understand?
What is an API?
Let's destructure the definition. An API technically stands for
- A - Application
P- Programming
- I - Interface
It is basically the bridge between your app's frontend and backend (server & database)
An APIs operates through ‘requests’ and ‘responses.’ When an API requests to access data from a web application or server, a response is expected. The location where the API sends a request and where the response emanates is what is known as an endpoint. Reputedly, the endpoint is the most crucial part of the API since it’s where the developer will implement to make their requests.
Endpoint
An API endpoint is the touchpoint of entry between an API and server, basically is one fancy word for a URL of a server/ service. It is a means by which an API fetches data from a server to perform a task.
For example: 127.0.0.8000/ get_items . get_items
is the endpoint
Endpoint Methods used
GET
- gets / returns data
POST
- creates new data
PUT
- updates data
DEL
- deletes data
What is FASTAPI
FastAPI is a modern, fast (high-performance), web framework for building APIs with Python 3.6+ based on standard Python type hints. Its key features include
Fast: Very high performance and on par with NodeJS and Go (thanks to Starlette for the web parts and Pydantic for the data parts). With it being one of the fastest Python frameworks available.
Fast to code: Increase the speed to develop features by about 200% to 300%.
Fewer bugs: Reduce about 40% of human (developer) induced errors.
Intuitive: Great editor support. Completion everywhere. Less time debugging.
Easy & Short: Designed to be very easy to use and learn. Less time reading docs. Trust me their docs are way easier and simpler. FASTAPI allows for minimised code duplication and multiple features from each parameter declaration.
Robust: Get production-ready code. With automatic interactive documentation. (That's the best part since you can also test your API in the docs without having to use POSTMAN) and it's based on (and fully compatible with) the open standards for APIs: OpenAPI (previously known as Swagger) and JSON Schema.
NB: FastApi has swagger embedded so it is easier to have a very nice API to test your data endpoints with
Now let's code
First, we install FASTAPI and a server called uvicorn
pip install fastapi
pip install uvicorn
Import module
from fastapi import FASTAPI
Create an instance
app = FASTAPI()
Start creating your API
@app.get("/")
def index():
return {"name": "First Item"}
Path Parameter
It is used to return data relating to an input
@app.get("/get-items/{items_id}")
def get_items(items_id: int = Path(None, description="Items ID you want to view")):
return items[items_id]
Query Parameter
A query is used to pass a value into a URL
@app.get("/get-by-name")
def get_items(*, name: Optional[str] = None, test: int):
for items_id in items:
if items[items_id]["name"] == name:
return items[items_id]
return {"error": "Item not found"}
Combining Query & Path Parameters
@app.get("/get-by-name/{items_id}")
def get_items(*, items_id: int, name: Optional[str] = None, test: int):
for items_id in items:
if items[items_id]["name"] == name:
return items[items_id]
return {"error": "Item not found"}
Request Body & Post Method
@app.post("/create-items/{items_id}")
def create_items(items_id: int, item: Items):
if items_id in items:
return {"error": "Item Already Exist"}
items[items_id] = item # create new object of item
return items[items_id]
Put Method
@app.put("/update-items/{items_id}")
def update_items(items_id: int, item: UpdateItem):
if items_id not in items:
return {"error": "Item does not exist"}
if item.name != None:
items[items_id].name = item.name # does not overide update if they are are none
if item.price != None:
items[items_id].name = item.price
if item.expiry_year != None:
items[items_id].name = item.expiry_year
items[items_id] = item
return items[items_id]
Delete Method
@app.delete("/delete-items/{items_id}")
def delete_items(items_id: int):
if items_id not in items:
return {"error": "Item does not exist"}
del items[items_id]
return {"message": "Item deleted successfully"}
Full code for the project
from fastapi import FastAPI, Path
from pydantic import BaseModel
from typing import Optional
app = FastAPI()
items = {
1: {"name": "rice", "price": 187, "expiry_year": 2024},
2: {"name": "beans", "price": 19, "expiry_year": 2031},
3: {"name": "sardine", "price": 201, "expiry_year": 2022},
4: {"name": "soap", "price": 21, "expiry_year": 2031},
5: {"name": "choco", "price": 50, "expiry_year": 2025},
}
class Items(BaseModel):
name: str
price: int
expiry_year: int
class UpdateItem(BaseModel):
name: Optional[str] = None
price: Optional[int] = None
expiry_year: Optional[int] = None
@app.get("/")
def index():
return {"item": "First Item"}
# Path Parameters
@app.get("/get-items/{items_id}")
def get_items(items_id: int = Path(None, description="Items ID you want to view")):
return items[items_id]
# Query Parameters
@app.get("/get-by-name")
def get_items(*, name: Optional[str] = None, test: int):
for items_id in items:
if items[items_id]["name"] == name:
return items[items_id]
return {"error": "Item not found"}
# Combining Query & Path Parameters
@app.get("/get-by-name/{items_id}")
def get_items(*, items_id: int, name: Optional[str] = None, test: int):
for items_id in items:
if items[items_id]["name"] == name:
return items[items_id]
return {"error": "Item not found"}
# Request Body & Post Methods
@app.post("/create-items/{items_id}")
def create_items(items_id: int, item: Items):
if items_id in items:
return {"error": "Item Already Exist"}
items[items_id] = item # create new object of item
return items[items_id]
# put method
@app.put("/update-items/{items_id}")
def update_items(items_id: int, item: UpdateItem):
if items_id not in items:
return {"error": "Item does not exist"}
if item.name != None:
items[items_id].name = item.name # does not overide update if they are are none
if item.price != None:
items[items_id].name = item.price
if item.expiry_year != None:
items[items_id].name = item.expiry_year
items[items_id] = item
return items[items_id]
@app.delete("/delete-items/{items_id}")
def delete_items(items_id: int):
if items_id not in items:
return {"error": "Item does not exist"}
del items[items_id]
return {"message": "Item deleted successfully"}