And the user auth stuff in NextJS is incredibly easy using the standard Next-Auth flow: https://next-auth.js.org/
You basically just set up a new application in the Google Cloud console, enable the Google Plus API for the app, and create the OAuth keys, and that's about it. Just add the secret key and identifier to your .env file for the NextJS app and it "just works".
You could essentially use a static JWT token that only that nexts cloud function knows?
Bit of an aside, whilst SQLModel and merging the API validation and ORM models is fast, is it a good idea? There could be reasons these two things should grow individually and is it good to put so much logic into external frameworks?
The beauty of how tiangolo (creator of FastAPI/SQLModel) implemented things is that an SQLModel class isn't just LIKE a pydantic schema and LIKE an SQLAlchemy ORM data model-- they literally ARE those things under the hood, so you can still use those libraries separately for more advanced tinkering and stuff "just works".
If that were the case, then using a PostgreSQL API[0] that maps tables to APIs would be all that's required.
However, the real world is messy. Requirements change, which could lead the project becoming a reimplementation of full framework such as Django.
Django also comes with generic REST endpoints based on models thus giving you the magic, but still allows for all the different use cases and customizations that might present themselves during the full lifecycle of a project.
Although those could also be Postgres views and stored procedures, of course.
My concern is that this breaks layering suggested by most architecture frameworks.
But this kind of thing can work in a well-architected system too. You're basically just saying this API is pure CRUD. I simply record what the client tells me. Then you have to apply your business rules somewhere else. This is usually the event-driven approach. I just record commands/events, then some other code actions those, based on business rules.
Where I think this goes wrong is not realising the business rules have to go somewhere else. I see this with Django a lot. You get started with just pure CRUD then someone says "oh, we shouldn't allow that record because xyz", and the whole thing starts to become a mess.
class Hero(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
name: str
secret_name: str
age: Optional[int] = None
Is the id supposed to be an Optional like that?Instead, it should distinguish between persisted entities and value objects:
class Entity(Generic[A]):
pk: int
val: A
class Hero:
name: str
secret_name: str
age: None | int = None
class Service(Generic[A]):
def persist(self, x: A) -> Entity[A]:
pk = self.execute(insert(x))
return Entity(pk, x)
def select(self, *cond) -> Iterable[Entity[A]]:
...
def copy(self, x: Entity[A]) -> Entity[A]:
return self.persist(x.val)
def delete(self, pk_ent: int | Entity[A]) -> A:
...
It should be obvious how the same model extends to different PK types too: serial ints, UUIDs, etc.(at least I'm assuming based on how other ORMs often (not always!) work)
We just released Omnio, a new AI model, that can do all this in a single step, as it works with audio directly. It does not generate a transcript and then modify it but can generate structured output such as Markdown directly from audio.
Maybe you can check it out.
Is anyone actually using FastAPI in a commercial, large scale app? Would you prefer using...say Django or Flask + Gevent (since they're more mature) over FastAPI?
I recently found this thread[1] about FastAPI. It's somewhat old now but reviews are mixed. I'm wondering if the landscape has improved now. Additionally, OP is using NextJS for the frontend and even that isn't without complaints[2]. What's odd for me is that the React website also asks you to pick between either Next.js or Remix[3].
[1] https://www.reddit.com/r/Python/comments/y4xuxb/fastapi_stab...
[2] https://www.reddit.com/r/nextjs/comments/1g18xgu/nextjs_is_h...
[3] https://react.dev/learn/start-a-new-react-project#production...
There's some gotchas in the way FastAPI works, mostly due to its usage of thread pools and the GIL. I would recommend anyone starting a project to exclusively use asynchronous I/O (SQLAlchemy supports async with asyncpg), as FastAPI is very clearly meant as a pure ASGI framework, despite what they claim.
When a route is async, it gets scheduled on the main event loop, meaning that any blocking calls can block all requests in flight, and block unexpected things like start up and teardown of api handlers. `asyncio.to_thread()` can help here, but it's easy to forget (and there's no warnings in case you forget).
If you do mix the two, I would be very careful to monitor the timings of your requests to detect early if blocking is occurring. For adding these metrics, I suggest using something like statsd or open-telemetry libraries for adding reporting to the endpoints, which you can feed into telemetry dashboards.
If you're forced to use a slower sync function (say, something from a library that you can't easily change), then you can use asyncio.to_thread() so that it can run in a separate thread without blocking your main event loop. If you don't do that, then you sort of defeat the whole purpose of the architecture because everything would stop while you're waiting for that slow sync function to return.
FastAPI will have more boilerplate, but I'm not sure that's an issue anymore in the age of AI coding assistants.
HTMX is also wonderful for both. It's a nice tech for lightweight SPAs. If you're going to go deeper into the JS side you can look at some of the more mature frameworks. I've been kinda partial to Vue.js.
And if you really want to go crazy there's pyscript from anaconda.
If you want to make a Django API these days I'd lean towards django-ninja which essentially bolts Pydantic onto Django, in a similar fashion to how FastAPI leverages Pydantic ontop of an async flask-like framework.
I personally would just use FastAPI but I understand lots of folks have invested heavily in (or prefer) Django's ORM to raw SQL or Alchemy.
Programming is a team sport and static types is just too useful and the bolted on typing is insufficient. We are burning, literally, millions of dollars in salaries to make python work at our org. It has been the same now at the four shops I've been a staff/principal level. Dynamic languages lend towards less maintainable code because the compiler offloads work to your squishy human working memory.
This is a bad idea in general and leads to all sorts of problems.
Despite having a big Django/DRF and FastAPI footprint, our backends in-development are using C#/aspnet.
In essence
solo dev: python is ok Tight teams: python not ok big corps where you literally can't even share code: python ok again.
Django and FastAPI are two different things. The former is a huge and opinionated MVC-like web framework and the latter is a simple library to make HTTP endpoints. I prefer FastAPI but it really depends of what you are building and how many people are going to work on that API.
> What's odd for me is that the React website also asks you to pick between either Next.js or Remix[3].
It's indeed very odd, they made this change with the new doc. I would not recommend to pick any of those and just start your project with vite.js, so you can focus on React and keep it simple. You can use react-router for the routes and react-query to call your backend. You don't really need anything else.
If you see performance issues or situations where youre hitting the n+1 query issue, you can optimize by using the orm’s prefetch_related, select_related, or just drop into raw sql.
Im obviously a fanperson, but have yet to find a framework combo that I like more than those two. It’s not very fashionable, but you’ll end up with an app thats quick to develop and thats reasonably secure by default.
If it's not working, then maybe maybe python the backend wasn't the best idea in the end?