HackerTrans
TopNewTrendsCommentsPastAskShowJobs

mr_Fatalyst

no profile record

Submissions

Show HN: Oxyde – Pydantic-native async ORM with a Rust core

github.com
155 points·by mr_Fatalyst·4 ay önce·81 comments

Show HN: FastOpenAPI – automated docs for many Python frameworks

github.com
153 points·by mr_Fatalyst·geçen yıl·77 comments

comments

mr_Fatalyst
·4 ay önce·discuss
Thanks, appreciate the support (^_^)!
mr_Fatalyst
·4 ay önce·discuss
The way I see it, having everything as Pydantic makes this natural. Your DB model, your request schema, your response DTO are all BaseModels. Converting between them is just model_dump() and model_validate(), or plain inheritance. No adapters, no mapping layers. So when you need to split things apart, it's straightforward rather than painful.
mr_Fatalyst
·4 ay önce·discuss
One thing that might help here: if you subclass an Oxyde model without defining class Meta: is_table = True, the child class won't be a table and won't have ORM behavior. So you can inherit the fields and validation but without save()/delete(). Not exactly a Protocol-based approach, but it gives you a clean read-only DTO derived from the same model.
mr_Fatalyst
·4 ay önce·discuss
Right now makemigrations detects add/drop/alter columns, indexes, foreign keys, and constraints. Rename is treated as drop + create, same as Django's default. Automatic rename detection is on the roadmap but not there yet. For now you'd edit the generated migration manually if you need a rename. Splitting a model into two would be detected as one dropped table and two new ones, so you'd also want to adjust that migration by hand to preserve data.
mr_Fatalyst
·4 ay önce·discuss
[dead]
mr_Fatalyst
·4 ay önce·discuss
That's exactly why Oxyde has no lazy loading at all. If you don't call .join() or .prefetch(), related data simply won't be there. N+1 is impossible by design, not by discipline.
mr_Fatalyst
·4 ay önce·discuss
Yep, there's a full comparison including SQLAlchemy async: https://oxyde.fatalyst.dev/latest/advanced/benchmarks/
mr_Fatalyst
·4 ay önce·discuss
Thanks! Not yet, it's still v0.5 and the API hasn't fully stabilized. But it's getting there.
mr_Fatalyst
·4 ay önce·discuss
1. We're all AI agents in a simulation anyway...

2. A converter still means maintaining two model systems. The point was to not have two in the first place.

3. MessagePack overhead is negligible compared to actual DB round-trips. And the Rust core isn't just SQL generation, it bundles the full driver stack (sqlx), pooling, and streaming, so you don't need asyncpg/aiosqlite as separate dependencies.
mr_Fatalyst
·4 ay önce·discuss
Well said, that's pretty much how I see it too. Thanks!
mr_Fatalyst
·4 ay önce·discuss
Right now it's CLI-based: 'oxyde migrate'. You can call 'apply_migrations()' programmatically, but that's not a publicly documented API yet. Good point though, worth adding.
mr_Fatalyst
·4 ay önce·discuss
Thanks! The admin panel supports Quart out of the box, so you should be good to go.
mr_Fatalyst
·4 ay önce·discuss
Good question. Working with Python objects in PyO3 requires holding the GIL. With MessagePack, Python serializes to bytes, hands them off, and Rust works completely GIL-free from that point. Same on the way back. So the GIL is held only for the brief serde step, not during SQL generation or execution.
mr_Fatalyst
·4 ay önce·discuss
You can't call filter() without a model. It's always Folder.objects.filter(user_id=user_id), so the context is right there in the code. Plus the generated .pyi stubs give your IDE full type info per model, so "go to usages" works through the type system.
mr_Fatalyst
·4 ay önce·discuss
Exactly, that's the idea.
mr_Fatalyst
·4 ay önce·discuss
For Oxyde specifically, it's still a young project, so the best public examples I have are the FastAPI tutorial (https://github.com/mr-fatalyst/fastapi-oxyde-example) and the admin panel examples (https://github.com/mr-fatalyst/oxyde-admin). Bigger real-world showcases will come with time. But in general, ORMs pay for themselves when you have lots of models, relations, and standard CRUD with validation. The moment you hand-write the same INSERT/UPDATE/SELECT with joins for every endpoint, it adds up fast.
mr_Fatalyst
·4 ay önce·discuss
Thanks! Haven't used Prisma much myself, but glad the approach resonates.
mr_Fatalyst
·4 ay önce·discuss
Thanks, appreciate it! Felt wrong to ship an ORM without one.
mr_Fatalyst
·4 ay önce·discuss
Right, it's not DBAPI compliant. The whole IO stack goes through Rust/sqlx, so PEP-249 doesn't apply. Oxyde has its own exception hierarchy (OxydeError, IntegrityError, NotFoundError, etc.). In practice most people catch ORM-level exceptions rather than DBAPI ones, but fair to call out.

On F(), good point. The descriptor approach is something I've been thinking about. Definitely on the radar.
mr_Fatalyst
·4 ay önce·discuss
Yeah, we're running out of ways to spell oxide (^_^)