Backend·Hacker News·1 lượt xem

Hiển thị HN: Oxyde – ORM không đồng bộ gốc Pydantic với lõi Rust

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

AI Summary

Oxyde là một ORM bất đồng bộ (async) mới, được xây dựng "native" với Pydantic, với mục tiêu loại bỏ việc khai báo model bị trùng lặp. Oxyde sử dụng Pydantic model làm nguồn chân lý duy nhất cho cả định nghĩa API và cơ sở dữ liệu. Nó giải quyết các vấn đề "đau đầu" thường gặp với ORM bằng cách cung cấp khả năng kiểm soát query tường minh, giúp ngăn chặn lỗi N+1, và tận dụng Pydantic để đảm bảo tính an toàn kiểu dữ liệu (type safety) và validation mạnh mẽ tại thời điểm chạy. Phần lõi của Oxyde được viết bằng Rust để tối ưu hóa việc sinh và thực thi câu lệnh SQL, trong khi Python sẽ xử lý logic nghiệp vụ và định nghĩa model. Điều này mang lại cho các developer một trải nghiệm ORM vừa an toàn về kiểu dữ liệu, vừa hiệu quả. Hãy cân nhắc Oxyde nếu bạn đang tìm kiếm một ORM hiện đại, tích hợp mượt mà với Pydantic và FastAPI, và ưu tiên khả năng kiểm soát tường minh cùng tính an toàn kiểu dữ liệu.

Tôi đã xây dựng Oxyde vì tôi cảm thấy mệt mỏi với việc sao chép các mô hình của mình.

Nếu bạn sử dụng FastAPI, bạn sẽ biết cách thực hiện. Bạn xác định các mô hình Pydantic cho API của mình, sau đó xác định các mô hình ORM riêng cho cơ sở dữ liệu của mình, sau đó viết các trình chuyển đổi giữa chúng. SQLModel cố gắng khắc phục điều này nhưng bên dưới vẫn là SQLAlchemy. Tortoise cung cấp cho bạn API kiểu Django đẹp mắt nhưng có hệ thống mô hình riêng. Django ORM rất tuyệt nhưng được hàn vào khung.

Tôi muốn một điều đơn giản: mô hình Pydantic LÀ mô hình cơ sở dữ liệu của bạn. Một lớp, xác thực đầy đủ về đầu vào và đầu ra, gợi ý kiểu gốc, không trùng lặp. API truy vấn có kiểu Django (.objects.filter(), .exclude(), biểu thức Q/F) vì tôi cho rằng đây là một trong những thiết kế tốt nhất hiện có.

Rõ ràng thay vì ngầm định. Tôi đã cố gắng loại bỏ tất cả những điều kỳ diệu. Các truy vấn không chạm đến cơ sở dữ liệu cho đến khi bạn gọi một phương thức đầu cuối như .all(), .get() hoặc .first(). Nếu bạn không gọi .join() hoặc .prefetch() một cách rõ ràng thì dữ liệu liên quan sẽ không được tải. Không tải chậm, không có truy vấn N+1 bất ngờ sau lưng bạn. Bạn biết chính xác những gì truy cập vào cơ sở dữ liệu bằng cách đọc mã.

An toàn loại là một động lực lớn. Điểm yếu của Python là những bất ngờ trong thời gian chạy, vì vậy Oxyde giải quyết vấn đề này theo ba cấp độ: (1) khi bạn chạy makemigrations, nó cũng tạo ra các tệp sơ khai .pyi với các truy vấn được nhập đầy đủ, để IDE của bạn biết rằng filter(age__gte=...) lấy một int, create() chấp nhận chính xác các trường mà mô hình của bạn có và .all() trả về list[User] không phải list[Any]; (2) Pydantic xác thực dữ liệu đi vào cơ sở dữ liệu; (3) Pydantic xác thực dữ liệu quay trở lại thông qua model_validate(). Bạn nhận được tính năng tự động hoàn thành, các dòng chữ ngoằn ngoèo màu đỏ ở lỗi chính tả và đảm bảo thời gian chạy, tất cả đều từ cùng một định nghĩa mô hình.

Tại sao lại là Rust? Không lấy tốc độ làm mục tiêu. Tôi không tranh luận về "ngôn ngữ X tốt hơn". Mỗi người đều giỏi những gì nó được tạo ra. Python khó có thể bị đánh bại trong việc thể hiện logic nghiệp vụ. Nhưng các công cụ cơ sở hạ tầng như tạo SQL, tổng hợp kết nối và tuần tự hóa hàng mới là nơi ngôn ngữ hệ thống có ý nghĩa. Vì vậy, tôi chia nó ra: Python xử lý các mô hình và logic nghiệp vụ của bạn, Rust xử lý hệ thống cơ sở dữ liệu. Các truy vấn được xây dựng dưới dạng IR trong Python, được tuần tự hóa thông qua MessagePack, được gửi đến Rust để tạo SQL dành riêng cho từng phương ngữ, thực thi nó và truyền kết quả trở lại. Tốc độ là một tác dụng phụ của sự phân chia này, không phải là mục tiêu. Nhưng vì bạn không phải trả thuế hiệu suất để thuận tiện nên đây là điểm chuẩn nếu tò mò: https://oxyde.fatalyst.dev/latest/advanced/benchmarks/

Hôm nay có gì: Di chuyển theo phong cách Django (makemigrations / di chuyển), giao dịch với các điểm lưu trữ, tham gia và tìm nạp trước, PostgreSQL + SQLite + MySQL, tích hợp FastAPI và bảng quản trị được tạo tự động hoạt động với FastAPI, Litestar, Sanic, Quart và Falcon (https://github.com/mr-fatalyst/oxyde-admin).

Đó là v0.5, beta, đang phát triển, API vẫn có thể thay đổi. Đây là nỗ lực của tôi để xây dựng ORM mà cá nhân tôi muốn sử dụng. Rất thích phản hồi, phê bình, ý tưởng.

Tài liệu: https://oxyde.fatalyst.dev/

Hướng dẫn FastAPI từng bước (API blog từ đầu): https://github.com/mr-fatalyst/fastapi-oxyde-example

Tác giả: mr_Fatalyst

#discussion