My API Server
This project is to produce a simple API server I can run locally with persistence because frankly the ones offered online are useless for serious testing and learning. This was done and run on LMDE and I was using HTTPie as my API client.
- Create a project folder. I called it myapiproject. IT doesn't lend itself to poetry.
- Open a terminal inside that folder (you could also do this from your IDE).
- Create a virtual environment: python -m venv venv — this will create a folder called venv inside your project folder.venv contains its own Python interpreter, its own site packages, and its own pip. Essentially it's a contained, isolated mini-Python.
- Activate the virtual environment (this is the only step that differs across platforms). On Linux: source venv/bin/activate; on Windows CMD: venv\Scripts\activate.bat. When successfully activated, your prompt will be preceded by venv.
- Inside your project folder, install FastAPI: pip install fastapi — this installs FastAPI, but only into that project environment. This is the point. You can have multiple projects and they won't interfere with each other.
- Create your main.py file inside your project folder. Mine looks like the following:
import json from pathlib import Path DATA_FILE = Path(__file__).parent / "todos.json" def load_data(): if DATA_FILE.exists(): with open(DATA_FILE, "r") as f: return json.load(f) return {} def save_data(data): with open(DATA_FILE, "w") as f: json.dump(data, f, indent=4) from fastapi import FastAPI, HTTPException from pydantic import BaseModel app = FastAPI() class Todo(BaseModel): id: int title: str completed: bool = False # Load persisted todos todos = load_data() @app.get("/") def read_root(): return {"message": "Your API is running"} @app.post("/todos") def create_todo(todo: Todo): key = str(todo.id) if key in todos: raise HTTPException(status_code=400, detail="ID already exists") todos[key] = todo.dict() save_data(todos) return todos[key] @app.get("/todos") def list_todos(): return list(todos.values()) @app.get("/todos/{todo_id}") def get_todo(todo_id: int): key = str(todo_id) if key not in todos: raise HTTPException(status_code=404, detail="Todo not found") return todos[key] @app.patch("/todos/{todo_id}") def update_todo(todo_id: int, data: dict): key = str(todo_id) if key not in todos: raise HTTPException(status_code=404, detail="Todo not found") updated = {**todos[key], **data} todos[key] = updated save_data(todos) return updated @app.delete("/todos/{todo_id}") def delete_todo(todo_id: int): key = str(todo_id) if key not in todos: raise HTTPException(status_code=404, detail="Todo not found") del todos[key] save_data(todos) return {"status": "deleted"}
With this done, shut everything down and, for the sake of clarity, start from scratch. This is all in a terminal. So:
That's it. You're done. You now have a useful API server with persistence you can expand upon and use for testing (NB: I used JSON as the fastest route to persistence; I know this doesn't scale).