A brief overview of FastApi
Coding in the age of Ai Watch out for Ai hallucinations!
- Copilot and ChatGPT (it works!)
- Ai generated flashcards (human in the loop)
- Memorable examples (storify)
- Readability (simple language,
academic writing)- Personally I find code hard to read at scale ...
- Or when each function has lots going on (multi-coloured!)
- RRReduce the amount you learn (or teach)
- The Python learning journey is f endless ...*
- Some things can be "they just are" without asking WHY.
- Stay in the shallows? Deep dive? It depends.
Limit Ai to give a fun example of the code (block), with a view to create cards later, as well as clarifying things as a study partner. My general process is: read, make notes (per chapter), condense notes, generate flashcards, files and programs. Creating a small series of books could come later.
"Give me a fun example for scaffolded learning on ____" "Give it to me as [draw!, missing, simple] data"
It's safe to say I'm not comfortable with backend and servers, so I want my experience and pleasant and simple as possible. SQLite is reasonable simple to use.
Some notes on using
uv
andvenv
setup1
- Hello World
- Routing (1.6.0 — 1.6.6)
- Response models and error handling (1.7.0 — 1.7.4)
- Templating with Jinja (1.8.0 — 1.8.2)
— 1.8.1 for
json
version - Structuring FastApi applications (1.9.0 — 1.9.1)
- Working with the database
- SQLModel (1.10.0 — 1.10.6)
MongoDB2 (I'm sticking with SQLite)
With SQLModel, some things that should be easy don't seem to be.
:id
not added to the Bruno path parameters (gettingmethod not allowed
)count()
fails hard: the alternative isfirst()
with SQLModel
uv run uvicorn api:app --port 8000 --reload
(or run from.venv
)uv run main.py
(if you've setup properly__main__.py
)
The major rule is to always BE CONSISTENT! There's a lot of small mistakes and continuity errors ... So use
⚠️ #!
style comments for major breaking code!
For example, pg.131:
NewUser
model is mentioned but not createdUser
fields are not yet usedUser.username
is used (curl
example) but not createdusers.py
is referred to asuser.py
Also
- Make sure any required dependencies are introduced clearly!
SQLModel
is imported, but no download is mentioned.
- Some "upgrades", such as
take time to learn@app.on_event("startup")
- The app lifecycle, for example, requires understanding of
contextlib
.
- The app lifecycle, for example, requires understanding of
You're going to need the following:
- Pydantic
- Uvicorn
- VS Code Python plugin
- MyPy (optional, runs slowly)
A great API test kit for Mac. Much simpler than the alternatives (IMO)
The only downsides to using Bruno is you've got to manually write your documentation and tests. FastApi comes with /docs
and /redoc
which are pretty handy, but the API testing isn't as nice. However, doing things in Bruno means we can easily switch to a different API framework and keep all our tests in place.
- Import
openapi.json
to a new collection
Rest Client, Postman3, and Insomnia are other options.
My general opinion is:
- Simple is better
- Smaller is better
- Less is better (dependencies)
- Human readable is better (docs)
- Boring is better (in general, stable)
- How do I generate
UUID
s (and what about performance?) - How do I load secrets and environment variables? with Pydantic?
- I think SQLite setup is a lot easier than Postgres
- Is async desirable with SQLite? (NEVER pre-optimise, wait until there's a need)
- The package is now deprecated, but there are 3rd party tools available.
- You might also be better off with RabbitMQ or some other queuing/sharding.
- Why would I use Peewee over SQLAlchemy or SQLModel?
Possibly better to do data migrations simply and often? Also may have to consider the
json
and client code (w/ business logic) Also handy isuser_version
which you can do like this.
- For simple changes, consider manually migrating
- You can also use ORM tools or something like alembic (depending on what ORM you're using)
- GUIs like Enso or Ai might be helpful too!
I really don't want to use Python's OOP style very much. The book is a bit sloppy in places with conflicting instructions.
json
is preferrable to.jinja
(at scale)4 (just use Elm?)- Try to avoid "magic" Python that isn't transferable
- Features like
@classmethod
,response_model=
are handy but not portable
- Features like
- Aim to keep your models, SQL, data, and code as simple as possible
- If you're unsure about something, possibly best to leave it out.
Whereas Elm has a central Model
(generally) to work from and uses modules and functions, Python has instances of classes which (I think) are stateful. It feels like Python adds a whole lot of mess to the code base.
A good example of this is FastAPI allows generating API examples along with your models. I feel the model and examples should be handled separately, and Bruno does this perfectly:
class ToDo(BaseModel):
id: int
item: Item
model_config = {
"json_schema_extra": {
"examples": [
{
"id": "1",
"item": {
"item": "Grab some shopping for dinner",
"status": "to-do"
}
}
]
}
}
/docs
gives a JSON Schema documentation ...
But to implement it looks like messy code. Things like Annotated[]
, "json_schema_extra"
, and so on. I'm finding that Bruno is pretty nice to work (as an alternative) with and does most of what I'd need.
These are annoying and compared to Elm (where everything just works), not particularly user-friendly. You'd think you could just run commands once you're set up with a
venv
(virtual environment).
- Dot notation: how are values extracted?
dictionary.id
rather thandictionary["id"]
- Module naming clashes and
venv
:**uv
commands require calling from thevenv
parent directory01
numbers cannot come first for module naming (name_01
is ok)
uvicorn
command won't run- Preface it with
uv run
(equivalent topython -m
) - Or, make sure you've
source .venv/bin/activate
d your environment - Also take care with modules, folders, and names.5
- Preface it with
uvicorn
doesn't allow securehttps
(by default)- Using Thonny as an IDE
- I can get the version of Python running but the other stuff is harder
- You might want to return
html
instead ofjson
. You can do both!
- AGSI setup in Python Anywhere
Footnotes
-
"I would not recommend using directory names in
.python-version
files or using a custom virtual environment name in a project." ↩ -
MongoDB is a an arse to setup (especially for beginners), more hassle than SQLite (and possibly Postgres easier also). The code in chapters
06
/07
and above also starts to get Pythonic (class methods rather than functional style) and I see diminishing returns from learning in the MongoDB style. ↩ -
I find Postman too flippin' complicated to use. Insomnia is another option. ↩
-
jinja
code adds a bit more complexity to your API code. Seems great for small setups but could prove a liability with complicated forms and UI. For now, handle most of the complexity with Elm lang and look into HTMX or static site generators for blog posts and FAQs. Possibly handleUser
admin with FastApi. ↩ -
There's two ways to do this. Either call
uvicorn subfolder.file:app
and make sure your modules usefrom subfolder.file
names, ORcd
into the correct folder and run Uvicorn from there! ↩