[HN Gopher] Making the Python back end for my new webapp
___________________________________________________________________
Making the Python back end for my new webapp
Author : eigenvalue
Score : 30 points
Date : 2024-10-16 15:08 UTC (7 hours ago)
(HTM) web link (youtubetranscriptoptimizer.com)
(TXT) w3m dump (youtubetranscriptoptimizer.com)
| bilekas wrote:
| Is your link working or maybe am I blocked on my network ?
|
| If it's not working, then maybe maybe python the backend wasn't
| the best idea in the end?
| eigenvalue wrote:
| It's working for me, and I see lots of traffic coming to it, so
| it's probably blocked for you. Most likely because it has
| "youtube" in the url!
| varun_chopra wrote:
| This post comes at a great time. I've been looking into what the
| "perfect" stack would be for me (I'm OK with Python but haven't
| done any frontend work).
|
| 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...
| ruicaridade wrote:
| Indeed, we use FastAPI in quite a large scale! I would not
| trade FastAPI for anything else at this point. Before the
| typing module became ubiquitous there used to be a lot of
| "magic" frameworks that made heavy use of Python's dynamic
| nature; both Django and Flask fall within this category: I am
| not a fan of untyped Python, at all.
|
| 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.
| nickpadge wrote:
| How is your experience with async SQLAlchemy with FastAPI?Ive
| experienced a handful of nasty bugs, specifically around how
| connection pooling is handled.
| bb88 wrote:
| Django/DRF are fine for API's particularly with DRF Spectacular
| to generate the Open API specs. DRF couples tightly to the ORM
| and plays nicely with the Django DB models.
|
| 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.
| eigenvalue wrote:
| FastAPI automatically generates the openapi.json file for
| you, which is how it's able to also give you the Swagger page
| "for free" once you've defined the route structure. It's very
| convenient.
| flakes wrote:
| Yup, I use FastAPI for some large services, handling a few
| million requests per day. Great experience overall, and speed
| of development is significantly improved. You can feel
| confident something is going to work after writing code. With
| flask and django I was always second guessing if things are
| hooked together properly. One pitfall I would avoid though is
| mixing both sync and asyncio together. Ive found there are a
| lot of footguns in that type of setup. Use one or the other,
| but not both
| E_Bfx wrote:
| Hello, could you elaborate on the footgun with mixing sync
| and asyncio ? I am currently devellopin one app with both
| kind of endpoint + websocket and I prefer not discover too
| late this problems .
| eigenvalue wrote:
| Basically, you want anything that has any kind of IO
| (network, disk, etc.) or which is very slow to compute to
| be fully async. If you have a function that returns almost
| instantly, like computing the hash of something, you can
| keep that sync.
|
| 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.
| flakes wrote:
| I've found that when mixing the two types of routes, it can
| be quite easy to accidentally introduce blocking paths
| which freeze up the main event loop, especially if mixing
| async dependencies with sync ones.
|
| 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.
| turtlebits wrote:
| I'd start with a pure server side stack like Flask or Django
| and forego the complexity of front-end JS.
| asplake wrote:
| Oh, SQLModel [1] looks interesting - hadn't seen that before. For
| apps with html front ends, are people replacing WTForms?
|
| [1] https://github.com/fastapi/sqlmodel
| eigenvalue wrote:
| It's such a game changer... I always had the thought before in
| the back of my mind, "Why do I need to create two versions of
| every data model that basically specify the same information
| (field name and type)?" And it turns out, you don't have to do
| that, you can use the same model for both the ORM and the
| response validation schema.
| asplake wrote:
| Right! And the forms too? Got to say though, even if it
| doesn't do the html generation that WTForms does, it seems
| the better split.
| eigenvalue wrote:
| No it doesn't do any forms stuff, but you can easily get
| the forms using your preferred UI framework from the data
| model definitions themselves using an LLM.
| Spivak wrote:
| Make sure you know the limitations of SQLModel before
| committing to it. It doesn't support polymorphism which was an
| immediate dq since that ends up being needed in every project.
| daft_pink wrote:
| I'm really interested in how you got the auth to interoperate
| between nextjs and python. I find auth to be the most difficult
| part of making blended code projects with JavaScript on the
| frontend like this.
| twolf910616 wrote:
| authn or authz? Authentication is not terrible to build but
| authorization yeah, I'm totally with you there. It's hard.
| eigenvalue wrote:
| Well you don't really need to get the auth to interoperate per
| se; the only machine that is allowed to connect to the FastAPI
| backend is the machine running the NextJS app, and it passes
| along the email address of the user making the request to the
| FastAPI backend.
|
| 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".
| daft_pink wrote:
| So essentially, you only let the server side rendering
| function, access the API and don't secure it at all beyond
| that?
|
| You could essentially use a static JWT token that only that
| nexts cloud function knows?
| eigenvalue wrote:
| Yeah, I restrict it by the IP address, so the FastAPI
| backend can only receive connections from localhost or the
| one machine running the NextJS app. There are certainly
| lots of ways you could restrict it, such as using a
| password or key.
| benn0 wrote:
| I've been doing this with NextAuth and fastapi-nextauth-js
| [https://github.com/TCatshoek/fastapi-nextauth-jwt]. With JWTs
| it's pretty straightforward to do something similar for any
| other auth provider. This is also using NextJS rewrites (see
| [https://vercel.com/templates/python/nextjs-fastapi-starter]
| for an example)
| dennisy wrote:
| Great article!
|
| 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?
| eigenvalue wrote:
| Thanks. I don't really see how the validation schema and ORM
| model would ever really diverge... it's basically just
| specifying the various fields that are required or expected and
| the types of those fields. Before I found SQLModel and I was
| separately using SQLAlchemy ORM and Pydantic, I would always
| end up with models that more or less looked the same but with
| just different syntax. And actually keeping them in sync was
| very annoying, since you would always have to remember to
| change things in both places. It's very natural to combine
| them.
|
| 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".
| dennisy wrote:
| Yeah I had a good read of the concept. I do agree for most
| CRUD apps there will be no divergence.
|
| My concern is that this breaks layering suggested by most
| architecture frameworks.
___________________________________________________________________
(page generated 2024-10-16 23:00 UTC)