├── server ├── __init__.py ├── api.py ├── model.py └── routes.py ├── .gitignore ├── requirements.txt ├── main.py ├── vercel.json └── README.MD /server/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__ 2 | .vercel 3 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | fastapi 2 | uvicorn 3 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | import uvicorn 2 | 3 | if __name__ == "__main__": 4 | uvicorn.run("server.api:app", host="0.0.0.0", port=8000, reload=True) 5 | -------------------------------------------------------------------------------- /vercel.json: -------------------------------------------------------------------------------- 1 | { 2 | "builds": [ 3 | {"src": "/server/api.py", "use": "@now/python"} 4 | ], 5 | "routes": [ 6 | {"src": "/(.*)", "dest": "server/api.py"} 7 | ] 8 | } -------------------------------------------------------------------------------- /server/api.py: -------------------------------------------------------------------------------- 1 | from fastapi import FastAPI 2 | from .routes import router as NoteRouter 3 | 4 | app = FastAPI() 5 | 6 | @app.get("/", tags=["Root"]) 7 | async def read_root() -> dict: 8 | return { 9 | "message": "Welcome to my notes application, use the /docs route to proceed" 10 | } 11 | 12 | app.include_router(NoteRouter, prefix="/note") -------------------------------------------------------------------------------- /server/model.py: -------------------------------------------------------------------------------- 1 | from typing import Optional 2 | 3 | from pydantic import BaseModel 4 | 5 | class NoteSchema(BaseModel): 6 | title: Optional[str] 7 | content: Optional[str] 8 | 9 | class Config: 10 | schema_extra = { 11 | "example": { 12 | "title": "LogRocket.", 13 | "content": "Logrocket is the most flexible publishing company for technical authors. From editors to payment, the process is too flexible and that's what makes it great." 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /README.MD: -------------------------------------------------------------------------------- 1 | # FastAPI Notes Application 2 | 3 | Repository containing code for "Deploying FastAPI applications to Vercel". 4 | 5 | ## Running the application 6 | 7 | To run the application on your machine, clone this repository and install the dependencies: 8 | 9 | ``` 10 | $ git clone https://github.com/Youngestdev/fastapi-notes-app && cd fastapi-notes-app 11 | ``` 12 | 13 | Setup a virtual environment: 14 | 15 | ``` 16 | $ virtualenv venv 17 | ``` 18 | 19 | Install dependencies: 20 | 21 | ``` 22 | $ pip3 install -r requirements.txt 23 | ``` 24 | 25 | Run the application: 26 | 27 | ``` 28 | pythom3 main.py 29 | ``` 30 | 31 | ## Error? 32 | 33 | If it's an error with regards to path, run the command: 34 | 35 | ``` 36 | export PYTHONPATH=$PWD 37 | ``` 38 | 39 | Any other one? Please raise an issue. -------------------------------------------------------------------------------- /server/routes.py: -------------------------------------------------------------------------------- 1 | from fastapi import APIRouter, Body 2 | from fastapi.encoders import jsonable_encoder 3 | from server.model import NoteSchema 4 | 5 | router = APIRouter() 6 | 7 | notes = { 8 | "1": { 9 | "title": "My first note", 10 | "content": "This is the first note in my notes application" 11 | }, 12 | "2": { 13 | "title": "Uniform circular motion.", 14 | "content": "Consider a body moving round a circle of radius r, wit uniform speed v as shown below. The speed everywhere is the same as v but direction changes as it moves round the circle." 15 | } 16 | } 17 | 18 | 19 | @router.get("/") 20 | def get_notes() -> dict: 21 | return { 22 | "data": notes 23 | } 24 | 25 | @router.get("/{id}") 26 | async def get_note(id: str) -> dict: 27 | if int(id) > len(notes): 28 | return { 29 | "error": "Invalid note ID" 30 | } 31 | 32 | for note in notes.keys(): 33 | if note == id: 34 | return { 35 | "data": notes[note] 36 | } 37 | 38 | return { 39 | "Error": "Invalid ID" 40 | } 41 | 42 | @router.post("/") 43 | def add_note(note: NoteSchema = Body(...)) -> dict: 44 | notes[str(len(notes)+1)] = note.dict() 45 | 46 | return { 47 | "message": "Note added successfully" 48 | } 49 | # 50 | @router.put("/{id}") 51 | def update_note(id: str, note: NoteSchema): 52 | stored_note = notes[id] 53 | if stored_note: 54 | stored_note_model = NoteSchema(**stored_note) 55 | update_data = note.dict(exclude_unset=True) 56 | updated_note = stored_note_model.copy(update=update_data) 57 | notes[id] = jsonable_encoder(updated_note) 58 | return { 59 | "message": "Note updated successfully" 60 | } 61 | return { 62 | "error": "No such note exist" 63 | } 64 | 65 | @router.delete("/{id}") 66 | def delete_note(id: str) -> dict: 67 | if int(id) > len(notes): 68 | return { 69 | "error": "Invalid note ID" 70 | } 71 | 72 | for note in notes.keys(): 73 | if note == id: 74 | del notes[note] 75 | return { 76 | "message": "Note deleted" 77 | } 78 | 79 | return { 80 | "error": "Note with {} doesn't exist".format(id) 81 | } 82 | 83 | --------------------------------------------------------------------------------