{"id":41452757,"url":"https://github.com/kent8192/reinhardt-web","last_synced_at":"2026-03-07T14:00:54.942Z","repository":{"id":320647358,"uuid":"1070756049","full_name":"kent8192/reinhardt-web","owner":"kent8192","description":"A composable full-stack API framework for Rust — Django's batteries-included philosophy meets Rust's performance and safety","archived":false,"fork":false,"pushed_at":"2026-03-05T09:57:05.000Z","size":31651,"stargazers_count":4,"open_issues_count":176,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-03-05T09:58:48.684Z","etag":null,"topics":["api-framework","async","authentication","dependency-injection","django","full-stack","graphql","modular","orm","rest-api","rust","web-framework","websockets"],"latest_commit_sha":null,"homepage":"https://reinhardt-web.dev","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kent8192.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-10-06T11:54:52.000Z","updated_at":"2026-03-05T09:57:08.000Z","dependencies_parsed_at":"2026-01-01T01:07:25.380Z","dependency_job_id":null,"html_url":"https://github.com/kent8192/reinhardt-web","commit_stats":null,"previous_names":["kent8192/reinhardt-rs","kent8192/reinhardt-web","kent8192/reinhardt"],"tags_count":587,"template":false,"template_full_name":null,"purl":"pkg:github/kent8192/reinhardt-web","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kent8192%2Freinhardt-web","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kent8192%2Freinhardt-web/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kent8192%2Freinhardt-web/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kent8192%2Freinhardt-web/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kent8192","download_url":"https://codeload.github.com/kent8192/reinhardt-web/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kent8192%2Freinhardt-web/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30216489,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-07T13:35:13.914Z","status":"ssl_error","status_checked_at":"2026-03-07T13:35:13.569Z","response_time":53,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api-framework","async","authentication","dependency-injection","django","full-stack","graphql","modular","orm","rest-api","rust","web-framework","websockets"],"created_at":"2026-01-23T15:30:54.533Z","updated_at":"2026-03-07T14:00:54.934Z","avatar_url":"https://github.com/kent8192.png","language":"Rust","readme":"\u003cdiv align=\"center\"\u003e\n  \u003cimg src=\"branding/logo.png\" alt=\"Reinhardt Logo\" width=\"200\"/\u003e\n\n  \u003ch1\u003eReinhardt\u003c/h1\u003e\n\n  \u003ch3\u003e🦀 Polylithic Batteries Included\u003c/h3\u003e\n\n  \u003cp\u003e\u003cstrong\u003eA composable full-stack API framework for Rust\u003c/strong\u003e\u003c/p\u003e\n  \u003cp\u003eBuild with \u003cem\u003eall\u003c/em\u003e the power of Django's batteries-included philosophy,\u003cbr/\u003e\n  or compose \u003cem\u003eonly\u003c/em\u003e what you need—your choice, your way.\u003c/p\u003e\n\n[![Crates.io](https://img.shields.io/crates/v/reinhardt-web.svg)](https://crates.io/crates/reinhardt-web)\n[![Documentation](https://docs.rs/reinhardt-web/badge.svg)](https://docs.rs/reinhardt-web)\n[![License](https://img.shields.io/badge/license-BSD--3--Clause-blue.svg)](LICENSE)\n[![codecov](https://codecov.io/gh/kent8192/reinhardt-web/graph/badge.svg)](https://codecov.io/gh/kent8192/reinhardt-web)\n[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/kent8192/reinhardt-web)\n\n🌐 **English** | [日本語](docs/readme-langs/README_JA.md) | [简体中文](docs/readme-langs/README_ZH_CN.md) | [繁體中文](docs/readme-langs/README_ZH_TW.md) | [Русский](docs/readme-langs/README_RU.md) | [Українська](docs/readme-langs/README_UK.md) | [فارسی](docs/readme-langs/README_FA.md) | [العربية](docs/readme-langs/README_AR.md)\n\n\u003c/div\u003e\n\n---\n\n## 📍 Quick Navigation\n\nYou may be looking for:\n\n- 🌐 [Official Website](https://reinhardt-web.dev) - Documentation, tutorials, and guides\n- 🚀 [Quick Start](#quick-start) - Get up and running in 5 minutes\n- 📦 [Installation Options](#installation) - Choose your flavor: Micro, Standard, or Full\n- 📚 [Getting Started Guide](https://reinhardt-web.dev/quickstart/getting-started/) - Step-by-step tutorial\n- 🎛️ [Feature Flags](https://reinhardt-web.dev/docs/feature-flags/) - Fine-tune your build\n- 📖 [API Documentation](https://docs.rs/reinhardt-web) - Complete API reference\n- 💬 [Community \u0026 Support](#getting-help) - Get help from the community\n\n## Why Reinhardt?\n\n**Polylithic = Poly (many) + Lithic (building blocks)**\nUnlike monolithic frameworks that force you to use everything, Reinhardt lets you compose your perfect stack from independent, well-tested components.\n\nReinhardt brings together the best of three worlds:\n\n| Inspiration        | What We Borrowed                                       | What We Improved                                     |\n|--------------------|--------------------------------------------------------|------------------------------------------------------|\n| 🐍 **Django**      | Batteries-included philosophy, ORM design, admin panel | Feature flags for composable builds, Rust's type safety |\n| 🎯 **Django REST** | Serializers, ViewSets, permissions                     | Compile-time validation, zero-cost abstractions      |\n| ⚡ **FastAPI**      | DI system, automatic OpenAPI                           | Native Rust performance, no runtime overhead         |\n| 🗄️ **SQLAlchemy** | QuerySet patterns, relationship handling               | Type-safe query builder, compile-time validation     |\n\n**Result**: A framework that's familiar to Python developers, but with Rust's performance and safety guarantees.\n\n## ✨ Key Features\n\n- **Type-Safe ORM** with compile-time validation (reinhardt-query)\n- **Powerful Serializers** with automatic validation (serde + validator)\n- **FastAPI-Style DI** with type-safe dependency injection and caching\n- **ViewSets** for rapid CRUD API development\n- **Multi-Auth** (JWT, Token, Session, Basic) with BaseUser/FullUser traits\n- **Admin Panel** with auto-generated model management interface\n- **Management Commands** for migrations, static files, and more\n- **GraphQL \u0026 WebSocket** support for real-time applications\n- **Pagination, Filtering, Rate Limiting** built-in\n- **Signals** for event-driven architecture\n\nSee [Available Components](#available-components) for complete list and [Getting Started](https://reinhardt-web.dev/quickstart/getting-started/) for examples.\n\n## Installation\n\nReinhardt is a modular framework. Choose your starting point:\n\n**Note on Crate Naming:**\nThe main Reinhardt crate is published on crates.io as `reinhardt-web`, but you import it as `reinhardt` in your code using the `package` attribute.\n\n### Default: Full-Featured (Batteries Included) ⚠️ New Default\n\nGet all features with zero configuration:\n\n```toml\n[dependencies]\n# Import as 'reinhardt', published as 'reinhardt-web'\n# Default enables ALL features (full bundle)\nreinhardt = { version = \"0.1.0-rc.1\", package = \"reinhardt-web\" }\n```\n\n**Includes:** Database, Auth, REST API, Admin, GraphQL, WebSockets, Cache, i18n, Mail, Sessions, Static Files, Storage\n\n**Binary**: ~50+ MB | **Compile**: Slower, but everything works out of the box\n\nThen use in your code:\n```rust\nuse reinhardt::prelude::*;\nuse reinhardt::{Request, Response, StatusCode};\n```\n\n### Option 1: Standard Setup (Balanced)\n\nFor most projects that don't need all features:\n\n```toml\n[dependencies]\nreinhardt = { version = \"0.1.0-rc.1\", package = \"reinhardt-web\", default-features = false, features = [\"standard\"] }\n```\n\n**Includes:** Core, Database (PostgreSQL), REST API, Auth, Middleware, Pages (WASM Frontend with SSR)\n\n**Binary**: ~20-30 MB | **Compile**: Medium\n\n### Option 2: Microservices (Minimal Setup)\n\nLightweight and fast, perfect for simple APIs:\n\n```toml\n[dependencies]\nreinhardt = { version = \"0.1.0-rc.1\", package = \"reinhardt-web\", default-features = false, features = [\"minimal\"] }\n```\n\n**Includes:** HTTP, routing, DI, parameter extraction, server\n\n**Binary**: ~5-10 MB | **Compile**: Very fast\n\n### Option 3: Build Your Custom Stack\n\nInstall only the components you need:\n\n```toml\n[dependencies]\n# Core components\nreinhardt-http = \"0.1.0-rc.1\"\nreinhardt-urls = \"0.1.0-rc.1\"\n\n# Optional: Database\nreinhardt-db = \"0.1.0-rc.1\"\n\n# Optional: Authentication\nreinhardt-auth = \"0.1.0-rc.1\"\n\n# Optional: REST API features\nreinhardt-rest = \"0.1.0-rc.1\"\n\n# Optional: Admin panel\nreinhardt-admin = \"0.1.0-rc.1\"\n\n# Optional: Advanced features\nreinhardt-graphql = \"0.1.0-rc.1\"\nreinhardt-websockets = \"0.1.0-rc.1\"\n```\n\n**📖 For a complete list of available crates and feature flags, see the [Feature Flags Guide](https://reinhardt-web.dev/docs/feature-flags/).**\n\n## Quick Start\n\n### 1. Install Reinhardt Admin Tool\n\n```bash\ncargo install reinhardt-admin-cli\n```\n\n### 2. Create a New Project\n\n```bash\n# Create a RESTful API project (default)\nreinhardt-admin startproject my-api\ncd my-api\n```\n\nThis generates a complete project structure:\n\n```\nmy-api/\n├── Cargo.toml\n├── src/\n│   ├── lib.rs\n│   ├── config.rs\n│   ├── apps.rs\n│   ├── config/\n│   │   ├── settings.rs\n│   │   ├── settings/\n│   │   │   ├── base.rs\n│   │   │   ├── local.rs\n│   │   │   ├── staging.rs\n│   │   │   └── production.rs\n│   │   ├── urls.rs\n│   │   └── apps.rs\n│   └── bin/\n│       └── manage.rs\n└── README.md\n```\n\n**Alternative: Create a reinhardt-pages Project (WASM + SSR)**\n\nFor a modern WASM-based frontend with SSR:\n\n```bash\n# Create a pages project\nreinhardt-admin startproject my-app --with-pages\ncd my-app\n\n# Install WASM build tools (first time only)\ncargo make install-wasm-tools\n\n# Build WASM and start development server\ncargo make dev\n# Visit http://127.0.0.1:8000/\n```\n\n### 3. Run the Development Server\n\n```bash\n# Using the manage command\ncargo run --bin manage runserver\n\n# Server will start at http://127.0.0.1:8000\n```\n\n**Auto-Reload Support:**\n\nFor automatic reloading on code changes (requires bacon):\n\n```bash\n# Install bacon\ncargo install --locked bacon\n\n# Run with auto-reload\nbacon runserver\n\n# Or use cargo make\ncargo make watch\n\n# For tests\nbacon test\n```\n\n### 4. Create Your First App\n\n```bash\n# Create a RESTful API app (default)\ncargo run --bin manage startapp users\n\n# Or explicitly specify type\ncargo run --bin manage startapp users --restful\n\n# Create a Pages app (WASM + SSR)\ncargo run --bin manage startapp dashboard --with-pages\n```\n\nThis creates an app structure:\n\n```\nusers/\n├── lib.rs\n├── models.rs\n├── models/\n├── views.rs\n├── views/\n├── serializers.rs\n├── serializers/\n├── admin.rs\n├── urls.rs\n└── tests.rs\n```\n\n### 5. Register Routes\n\nEdit your app's `urls.rs`:\n\n```rust\n// users/urls.rs\nuse reinhardt::ServerRouter;\n\nuse super::views;\n\npub fn url_patterns() -\u003e ServerRouter {\n\tServerRouter::new()\n\t\t.endpoint(views::list_users)\n\t\t.endpoint(views::get_user)\n\t\t.endpoint(views::create_user)\n}\n```\n\nInclude in `src/config/urls.rs`:\n\n```rust\n// src/config/urls.rs\nuse reinhardt::prelude::*;\nuse reinhardt::routes;\n\n#[routes]\npub fn routes() -\u003e ServerRouter {\n\tServerRouter::new()\n\t\t.mount(\"/api/\", users::urls::url_patterns())\n}\n```\n\nThe `#[routes]` attribute macro automatically registers this function with the\nframework for discovery via the `inventory` crate.\n\n**Note:** The `reinhardt::prelude` includes commonly used types. Key exports include:\n\n**Always Available:**\n- Core routing and views: `Router`, `DefaultRouter`, `ServerRouter`, `View`, `ListView`, `DetailView`\n- ViewSets: `ViewSet`, `ModelViewSet`, `ReadOnlyModelViewSet`\n- HTTP: `StatusCode`\n\n**Feature-Dependent:**\n- **`core` feature**: `Request`, `Response`, `Handler`, `Middleware`, Signals (`post_save`, `pre_save`, etc.)\n- **`database` feature**: `Model`, `DatabaseConnection`, `F`, `Q`, `Transaction`, `atomic`, Database functions (`Concat`, `Upper`, `Lower`, `Now`, `CurrentDate`), Window functions (`Window`, `RowNumber`, `Rank`, `DenseRank`), Constraints (`UniqueConstraint`, `CheckConstraint`, `ForeignKeyConstraint`)\n- **`auth` feature**: `User`, `UserManager`, `GroupManager`, `Permission`, `ObjectPermission`\n- **`minimal`, `standard`, or `di` features**: `Body`, `Cookie`, `Header`, `Json`, `Path`, `Query`\n- **`rest` feature**: Serializers, Parsers, Pagination, Throttling, Versioning\n- **`admin` feature**: Admin panel components\n- **`cache` feature**: `Cache`, `InMemoryCache`\n- **`sessions` feature**: `Session`, `AuthenticationMiddleware`\n\nFor a complete list, see [Feature Flags Guide](https://reinhardt-web.dev/docs/feature-flags/).\n\nFor a complete step-by-step guide, see [Getting Started](https://reinhardt-web.dev/quickstart/getting-started/).\n\n## 🎓 Learn by Example\n\n### With Database\n\nConfigure database in `settings/base.toml`:\n\n```toml\ndebug = true\nsecret_key = \"your-secret-key-for-development\"\n\n[database]\nengine = \"postgresql\"\nhost = \"localhost\"\nport = 5432\nname = \"mydb\"\nuser = \"postgres\"\npassword = \"postgres\"\n```\n\nSettings are automatically loaded in `src/config/settings.rs`:\n\n```rust\n// src/config/settings.rs\nuse reinhardt::conf::settings::builder::SettingsBuilder;\nuse reinhardt::conf::settings::profile::Profile;\nuse reinhardt::conf::settings::sources::{DefaultSource, LowPriorityEnvSource, TomlFileSource};\nuse reinhardt::core::Settings;\nuse std::env;\nuse std::path::PathBuf;\nuse std::str::FromStr;\n\npub fn get_settings() -\u003e Settings {\n\tlet profile_str = env::var(\"REINHARDT_ENV\").unwrap_or_else(|_| \"local\".to_string());\n\tlet profile = Profile::from_str(\u0026profile_str).unwrap_or(Profile::Development);\n\n\tlet base_dir = env::current_dir().expect(\"Failed to get current directory\");\n\tlet settings_dir = base_dir.join(\"settings\");\n\n\tlet merged = SettingsBuilder::new()\n\t\t.profile(profile)\n\t\t.add_source(\n\t\t\tDefaultSource::new()\n\t\t\t\t.with_value(\"debug\", serde_json::Value::Bool(false))\n\t\t\t\t.with_value(\"language_code\", serde_json::Value::String(\"en-us\".to_string()))\n\t\t\t\t.with_value(\"time_zone\", serde_json::Value::String(\"UTC\".to_string()))\n\t\t)\n\t\t.add_source(LowPriorityEnvSource::new().with_prefix(\"REINHARDT_\"))\n\t\t.add_source(TomlFileSource::new(settings_dir.join(\"base.toml\")))\n\t\t.add_source(TomlFileSource::new(settings_dir.join(format!(\"{}.toml\", profile_str))))\n\t\t.build()\n\t\t.expect(\"Failed to build settings\");\n\n\tmerged.into_typed().expect(\"Failed to convert settings to Settings struct\")\n}\n```\n\n**Environment Variable Sources:**\n\nReinhardt provides two types of environment variable sources with different priorities:\n\n- **`EnvSource`** (priority: 100) - High priority environment variables that override TOML files\n  ```rust\n  .add_source(EnvSource::new().with_prefix(\"REINHARDT_\"))\n  ```\n\n- **`LowPriorityEnvSource`** (priority: 40) - Low priority environment variables that fall back to TOML files\n  ```rust\n  .add_source(LowPriorityEnvSource::new().with_prefix(\"REINHARDT_\"))\n  ```\n\n**Priority Order**:\n- Using `EnvSource`: Environment Variables \u003e `{profile}.toml` \u003e `base.toml` \u003e Defaults\n- Using `LowPriorityEnvSource` (shown above): `{profile}.toml` \u003e `base.toml` \u003e Environment Variables \u003e Defaults\n\nChoose `EnvSource` when environment variables should always take precedence (e.g., production deployments).\nChoose `LowPriorityEnvSource` when TOML files should be the primary configuration source (e.g., development).\n\nSee [Settings Documentation](docs/SETTINGS_DOCUMENT.md) for more details.\n\n**Using the Built-in DefaultUser:**\n\nReinhardt provides a ready-to-use `DefaultUser` implementation (requires `argon2-hasher` feature):\n\n```rust\n// users/models.rs\nuse reinhardt::prelude::*;\nuse reinhardt::DefaultUser;\n\n// Re-export DefaultUser as User for your app\npub type User = DefaultUser;\n\n// DefaultUser includes:\n// - id: Uuid (primary key)\n// - username: String\n// - email: String\n// - password_hash: Option\u003cString\u003e\n// - first_name: String\n// - last_name: String\n// - is_active: bool\n// - is_staff: bool\n// - is_superuser: bool\n// - last_login: Option\u003cDateTime\u003cUtc\u003e\u003e\n// - date_joined: DateTime\u003cUtc\u003e\n\n// DefaultUser implements:\n// - BaseUser trait (authentication methods)\n// - FullUser trait (full user information)\n// - PermissionsMixin trait (permission management)\n// - Model trait (database operations)\n```\n\n**Defining Custom User Models:**\n\nIf you need custom fields, define your own model:\n\n```rust\n// users/models.rs\nuse reinhardt::prelude::*;\nuse serde::{Serialize, Deserialize};\nuse chrono::{DateTime, Utc};\n\n#[model(app_label = \"users\", table_name = \"users\")]\npub struct CustomUser {\n\t#[field(primary_key = true)]\n\tpub id: i64,\n\n\t#[field(max_length = 255)]\n\tpub email: String,\n\n\t#[field(max_length = 100)]\n\tpub username: String,\n\n\t#[field(default = true)]\n\tpub is_active: bool,\n\n\t#[field(auto_now_add = true)]\n\tpub created_at: DateTime\u003cUtc\u003e,\n\n\t// Add custom fields\n\t#[field(max_length = 50, null = true)]\n\tpub phone_number: Option\u003cString\u003e,\n}\n```\n\n**Model Attribute Macro:**\n\nThe `#[model(...)]` attribute automatically generates:\n- Implementation of the `Model` trait (includes `#[derive(Model)]` functionality)\n- Type-safe field accessors: `User::field_email()`, `User::field_username()`, etc.\n- Global model registry registration\n- Support for composite primary keys\n\n**Note:** When using `#[model(...)]`, you do NOT need to add `#[derive(Model)]` separately,\nas it is automatically applied by the `#[model(...)]` attribute.\n\n**Field Attributes:**\n- `#[field(primary_key = true)]` - Mark as primary key\n- `#[field(max_length = 255)]` - Set maximum length for string fields\n- `#[field(default = value)]` - Set default value\n- `#[field(auto_now_add = true)]` - Auto-populate timestamp on creation\n- `#[field(auto_now = true)]` - Auto-update timestamp on save\n- `#[field(null = true)]` - Allow NULL values\n- `#[field(unique = true)]` - Enforce uniqueness constraint\n\nFor a complete list of field attributes, see the [Field Attributes Guide](docs/field_attributes.md).\n\nThe generated field accessors enable type-safe field references in queries:\n\n```rust\n// Generated by #[model(...)] for DefaultUser\nimpl DefaultUser {\n\tpub const fn field_id() -\u003e FieldRef\u003cDefaultUser, Uuid\u003e { FieldRef::new(\"id\") }\n\tpub const fn field_username() -\u003e FieldRef\u003cDefaultUser, String\u003e { FieldRef::new(\"username\") }\n\tpub const fn field_email() -\u003e FieldRef\u003cDefaultUser, String\u003e { FieldRef::new(\"email\") }\n\tpub const fn field_is_active() -\u003e FieldRef\u003cDefaultUser, bool\u003e { FieldRef::new(\"is_active\") }\n\tpub const fn field_is_staff() -\u003e FieldRef\u003cDefaultUser, bool\u003e { FieldRef::new(\"is_staff\") }\n\tpub const fn field_date_joined() -\u003e FieldRef\u003cDefaultUser, DateTime\u003cUtc\u003e\u003e { FieldRef::new(\"date_joined\") }\n\t// ... other fields\n}\n```\n\n**Advanced Query Examples:**\n\n```rust\nuse reinhardt::prelude::*;\nuse reinhardt::DefaultUser;\n\n// Django-style F/Q object queries with type-safe field references\nasync fn complex_user_query() -\u003e Result\u003cVec\u003cDefaultUser\u003e, Box\u003cdyn std::error::Error\u003e\u003e {\n\t// Q objects with type-safe field references (using generated field accessors)\n\tlet active_query = Q::new()\n\t\t.field(\"is_active\").eq(true)\n\t\t.and(Q::new().field(\"date_joined\").gte(Now::new()));\n\n\t// Database functions with type-safe field references\n\tlet email_lower = Lower::new(DefaultUser::field_email().into());\n\tlet username_upper = Upper::new(DefaultUser::field_username().into());\n\n\t// Aggregations using field accessors\n\tlet user_count = Aggregate::count(DefaultUser::field_id().into());\n\tlet latest_joined = Aggregate::max(DefaultUser::field_date_joined().into());\n\n\t// Window functions for ranking\n\tlet rank_by_join_date = Window::new()\n\t\t.partition_by(vec![DefaultUser::field_is_active().into()])\n\t\t.order_by(vec![(DefaultUser::field_date_joined().into(), \"DESC\")])\n\t\t.function(RowNumber::new());\n\n\ttodo!(\"Execute query with these components\")\n}\n\n// Transaction support\nasync fn create_user_with_transaction(\n\tconn: \u0026DatabaseConnection,\n\tuser_data: CreateUserRequest\n) -\u003e Result\u003cUser, Box\u003cdyn std::error::Error\u003e\u003e {\n\t// Transaction with automatic rollback on error\n\ttransaction(conn, |_tx| async move {\n\t\tlet user = User::create(user_data).await?;\n\t\tlog_user_creation(\u0026user).await?;\n\t\tOk(user)\n\t}).await\n}\n```\n\n**Note**: Reinhardt uses reinhardt-query for SQL operations. The `#[derive(Model)]` macro automatically generates Model trait implementations, type-safe field accessors, and global model registry registration.\n\nRegister in `src/config/apps.rs`:\n\n```rust\n// src/config/apps.rs\nuse reinhardt::installed_apps;\n\n// The installed_apps! macro generates:\n// - An enum InstalledApp with variants for each app\n// - Implementation of conversion traits (From, Into, Display)\n// - A registry for app configuration and discovery\n//\n// Note: Unlike Django's INSTALLED_APPS, this macro is for user apps only.\n// Built-in framework features (auth, sessions, admin, etc.) are enabled via\n// Cargo feature flags, not through installed_apps!.\n//\n// Example:\n// [dependencies]\n// reinhardt = { version = \"0.1\", features = [\"auth\", \"sessions\", \"admin\"] }\n//\n// This enables:\n// - Automatic app discovery for migrations, admin panel, etc.\n// - Type-safe app references throughout your code\n// - Centralized app configuration\ninstalled_apps! {\n\tusers: \"users\",\n}\n\npub fn get_installed_apps() -\u003e Vec\u003cString\u003e {\n\tInstalledApp::all_apps()\n}\n```\n\n### With Authentication\n\nReinhardt provides Django-style user models with `BaseUser` and `FullUser` traits, along with comprehensive user management through `UserManager`.\n\n**Note:** Reinhardt includes a built-in `DefaultUser` implementation. You can use it directly or define your own user model as shown below.\n\n**User Management Example:**\n\n```rust\nuse reinhardt::prelude::*;\n\n// Create and manage users with UserManager\nasync fn manage_users() -\u003e Result\u003c(), Box\u003cdyn std::error::Error\u003e\u003e {\n\tlet hasher = Argon2Hasher::new();\n\tlet user_manager = UserManager::new(hasher);\n\n\t// Create a new user\n\tlet user = user_manager.create_user(CreateUserData {\n\t\tusername: \"alice\".to_string(),\n\t\temail: \"alice@example.com\".to_string(),\n\t\tpassword: \"secure_password\".to_string(),\n\t\tfirst_name: Some(\"Alice\".to_string()),\n\t\tlast_name: Some(\"Smith\".to_string()),\n\t}).await?;\n\n\t// Update user information\n\tuser_manager.update_user(user.id, UpdateUserData {\n\t\temail: Some(\"alice.smith@example.com\".to_string()),\n\t\tis_active: Some(true),\n\t\t..Default::default()\n\t}).await?;\n\n\t// Manage groups and permissions\n\tlet group_manager = GroupManager::new();\n\tlet editors = group_manager.create_group(CreateGroupData {\n\t\tname: \"editors\".to_string(),\n\t}).await?;\n\n\t// Assign object-level permissions\n\tlet permission = ObjectPermission::new(\"edit\", user.id, article.id);\n\tlet perm_checker = ObjectPermissionChecker::new();\n\tif perm_checker.has_permission(\u0026user, \"edit\", \u0026article).await? {\n\t\t// User can edit the article\n\t}\n\n\tOk(())\n}\n```\n\nUse the built-in `DefaultUser` in `users/models.rs`:\n\n```rust\n// users/models.rs\nuse reinhardt::DefaultUser;\n\n// Re-export DefaultUser as your User type\npub type User = DefaultUser;\n\n// DefaultUser already implements:\n// - BaseUser trait (authentication methods)\n// - FullUser trait (username, email, first_name, last_name, etc.)\n// - PermissionsMixin trait (permission management)\n// - Model trait (database operations)\n```\n\n**For Custom User Models:**\n\nIf you need additional fields beyond DefaultUser, define your own:\n\n```rust\n// users/models.rs\nuse reinhardt::auth::{BaseUser, FullUser, PermissionsMixin};\nuse uuid::Uuid;\nuse chrono::{DateTime, Utc};\nuse serde::{Serialize, Deserialize};\n\n#[model(app_label = \"users\", table_name = \"users\")]\npub struct CustomUser {\n\t#[field(primary_key = true)]\n\tpub id: Uuid,\n\n\t#[field(max_length = 150)]\n\tpub username: String,\n\n\t#[field(max_length = 255)]\n\tpub email: String,\n\n\tpub password_hash: Option\u003cString\u003e,\n\n\t#[field(max_length = 150)]\n\tpub first_name: String,\n\n\t#[field(max_length = 150)]\n\tpub last_name: String,\n\n\t#[field(default = true)]\n\tpub is_active: bool,\n\n\t#[field(default = false)]\n\tpub is_staff: bool,\n\n\t#[field(default = false)]\n\tpub is_superuser: bool,\n\n\tpub last_login: Option\u003cDateTime\u003cUtc\u003e\u003e,\n\n\t#[field(auto_now_add = true)]\n\tpub date_joined: DateTime\u003cUtc\u003e,\n\n\t// Custom fields\n\t#[field(max_length = 20, null = true)]\n\tpub phone_number: Option\u003cString\u003e,\n}\n\nimpl BaseUser for CustomUser {\n\ttype PrimaryKey = Uuid;\n\n\tfn get_username_field() -\u003e \u0026'static str { \"username\" }\n\tfn get_username(\u0026self) -\u003e \u0026str { \u0026self.username }\n\tfn password_hash(\u0026self) -\u003e Option\u003c\u0026str\u003e { self.password_hash.as_deref() }\n\tfn set_password_hash(\u0026mut self, hash: String) { self.password_hash = Some(hash); }\n\tfn last_login(\u0026self) -\u003e Option\u003cDateTime\u003cUtc\u003e\u003e { self.last_login }\n\tfn set_last_login(\u0026mut self, time: DateTime\u003cUtc\u003e) { self.last_login = Some(time); }\n\tfn is_active(\u0026self) -\u003e bool { self.is_active }\n}\n\nimpl FullUser for CustomUser {\n\tfn username(\u0026self) -\u003e \u0026str { \u0026self.username }\n\tfn email(\u0026self) -\u003e \u0026str { \u0026self.email }\n\tfn first_name(\u0026self) -\u003e \u0026str { \u0026self.first_name }\n\tfn last_name(\u0026self) -\u003e \u0026str { \u0026self.last_name }\n\tfn is_staff(\u0026self) -\u003e bool { self.is_staff }\n\tfn is_superuser(\u0026self) -\u003e bool { self.is_superuser }\n\tfn date_joined(\u0026self) -\u003e DateTime\u003cUtc\u003e { self.date_joined }\n}\n```\n\nUse JWT authentication in your app's `views/profile.rs`:\n\n```rust\n// users/views/profile.rs\nuse reinhardt::auth::{JwtAuth, BaseUser};\nuse reinhardt::{Request, Response, StatusCode, ViewResult, get};\nuse reinhardt::db::DatabaseConnection;\nuse std::sync::Arc;\nuse crate::models::User;\n\n#[get(\"/profile\", name = \"get_profile\")]\npub async fn get_profile(\n\treq: Request,\n\t#[inject] db: Arc\u003cDatabaseConnection\u003e,\n) -\u003e ViewResult\u003cResponse\u003e {\n\t// Extract JWT token from Authorization header\n\tlet auth_header = req.headers.get(\"authorization\")\n\t\t.and_then(|h| h.to_str().ok())\n\t\t.ok_or(\"Missing Authorization header\")?;\n\n\tlet token = auth_header.strip_prefix(\"Bearer \")\n\t\t.ok_or(\"Invalid Authorization header format\")?;\n\n\t// Verify token and get user ID\n\tlet jwt_auth = JwtAuth::new(b\"your-secret-key\");\n\tlet claims = jwt_auth.verify_token(token)?;\n\n\t// Load user from database using claims.user_id\n\tlet user = User::find_by_id(\u0026db, \u0026claims.user_id).await?;\n\n\t// Check if user is active\n\tif !user.is_active() {\n\t\treturn Err(\"User account is inactive\".into());\n\t}\n\n\t// Return user profile as JSON\n\tlet json = serde_json::to_string(\u0026user)?;\n\tOk(Response::new(StatusCode::OK)\n\t\t.with_body(json))\n}\n```\n\n### Endpoint Definition\n\nReinhardt uses HTTP method decorators to define endpoints:\n\n#### HTTP Method Decorators\n\nUse `#[get]`, `#[post]`, `#[put]`, `#[delete]` to define routes:\n\n```rust\nuse reinhardt::{get, post, Request, Response, ViewResult};\nuse serde_json::json;\n\n#[get(\"/\")]\npub async fn hello(_req: Request) -\u003e ViewResult\u003cResponse\u003e {\n\tOk(Response::ok().with_body(\"Hello, World!\"))\n}\n\n#[post(\"/users\")]\npub async fn create_user(_req: Request) -\u003e ViewResult\u003cResponse\u003e {\n\tlet body = json!({\"status\": \"created\"});\n\tResponse::ok().with_json(\u0026body).map_err(Into::into)\n}\n```\n\n**Features:**\n- Compile-time path validation\n- Concise syntax\n- Automatic HTTP method binding\n- Support for dependency injection via `#[inject]`\n\n#### Using Dependency Injection\n\nCombine HTTP method decorators with `#[inject]` for automatic dependency injection:\n\n```rust\nuse reinhardt::{get, Request, Response, StatusCode, ViewResult};\nuse reinhardt::db::DatabaseConnection;\nuse std::sync::Arc;\n\n#[get(\"/users/{id}/\", name = \"get_user\")]\npub async fn get_user(\n\treq: Request,\n\t#[inject] db: Arc\u003cDatabaseConnection\u003e,  // Automatically injected\n) -\u003e ViewResult\u003cResponse\u003e {\n\tlet id = req.path_params.get(\"id\")\n\t\t.ok_or(\"Missing id\")?\n\t\t.parse::\u003ci64\u003e()?;\n\n\t// Use injected database connection\n\tlet user = db.query(\"SELECT * FROM users WHERE id = $1\")\n\t\t.bind(id)\n\t\t.fetch_one()\n\t\t.await?;\n\n\tlet json = serde_json::to_string(\u0026user)?;\n\tOk(Response::new(StatusCode::OK)\n\t\t.with_body(json))\n}\n```\n\n**Dependency Injection Features:**\n- Automatic dependency injection via `#[inject]` attribute\n- Cache control with `#[inject(cache = false)]`\n- FastAPI-inspired dependency injection system\n- Works seamlessly with HTTP method decorators\n\n**Result Type:**\n\nAll view functions use `ViewResult\u003cT\u003e` as the return type:\n\n```rust\nuse reinhardt::ViewResult;  // Pre-defined result type\n```\n\n### With Parameter Extraction\n\nIn your app's `views/user.rs`:\n\n```rust\n// users/views/user.rs\nuse reinhardt::{Request, Response, StatusCode, ViewResult, get};\nuse reinhardt::db::DatabaseConnection;\nuse crate::models::User;\nuse std::sync::Arc;\n\n#[get(\"/users/{id}/\", name = \"get_user\")]\npub async fn get_user(\n\treq: Request,\n\t#[inject] db: Arc\u003cDatabaseConnection\u003e,\n) -\u003e ViewResult\u003cResponse\u003e {\n\t// Extract path parameter from request\n\tlet id = req.path_params.get(\"id\")\n\t\t.ok_or(\"Missing id parameter\")?\n\t\t.parse::\u003ci64\u003e()\n\t\t.map_err(|_| \"Invalid id format\")?;\n\n\t// Extract query parameters (e.g., ?include_inactive=true)\n\tlet include_inactive = req.query_params.get(\"include_inactive\")\n\t\t.and_then(|v| v.parse::\u003cbool\u003e().ok())\n\t\t.unwrap_or(false);\n\n\t// Fetch user from database using injected connection\n\tlet user = User::find_by_id(\u0026db, id).await?;\n\n\t// Check active status if needed\n\tif !include_inactive \u0026\u0026 !user.is_active {\n\t\treturn Err(\"User is inactive\".into());\n\t}\n\n\t// Return as JSON\n\tlet json = serde_json::to_string(\u0026user)?;\n\tOk(Response::new(StatusCode::OK)\n\t\t.with_body(json))\n}\n```\n\nRegister route with path parameter in `urls.rs`:\n\n```rust\n// users/urls.rs\nuse reinhardt::ServerRouter;\n\nuse super::views;\n\npub fn url_patterns() -\u003e ServerRouter {\n\tServerRouter::new()\n\t\t.endpoint(views::get_user)  // Path defined in #[get(\"/users/{id}/\")]\n}\n```\n\n### With Serializers and Validation\n\nIn your app's `serializers/user.rs`:\n\n```rust\n// users/serializers/user.rs\nuse serde::{Serialize, Deserialize};\nuse validator::Validate;\n\n#[derive(Serialize, Deserialize, Validate)]\npub struct CreateUserRequest {\n\t#[validate(email)]\n\tpub email: String,\n\t#[validate(length(min = 3, max = 50))]\n\tpub username: String,\n\t#[validate(length(min = 8))]\n\tpub password: String,\n}\n\n#[derive(Serialize, Deserialize)]\npub struct UserResponse {\n\tpub id: i64,\n\tpub username: String,\n\tpub email: String,\n\tpub is_active: bool,\n}\n\nimpl From\u003cUser\u003e for UserResponse {\n\tfn from(user: User) -\u003e Self {\n\t\tUserResponse {\n\t\t\tid: user.id,\n\t\t\tusername: user.username,\n\t\t\temail: user.email,\n\t\t\tis_active: user.is_active,\n\t\t}\n\t}\n}\n```\n\nIn your app's `views/user.rs`:\n\n```rust\n// users/views/user.rs\nuse reinhardt::{Request, Response, StatusCode, ViewResult, post};\nuse reinhardt::db::DatabaseConnection;\nuse crate::models::User;\nuse crate::serializers::{CreateUserRequest, UserResponse};\nuse validator::Validate;\nuse std::sync::Arc;\n\n#[post(\"/users\", name = \"create_user\")]\npub async fn create_user(\n\tmut req: Request,\n\t#[inject] db: Arc\u003cDatabaseConnection\u003e,\n) -\u003e ViewResult\u003cResponse\u003e {\n\t// Parse request body\n\tlet body_bytes = std::mem::take(\u0026mut req.body);\n\tlet create_req: CreateUserRequest = serde_json::from_slice(\u0026body_bytes)?;\n\n\t// Validate request\n\tcreate_req.validate()?;\n\n\t// Create user\n\tlet mut user = User {\n\t\tid: 0, // Will be set by database\n\t\tusername: create_req.username,\n\t\temail: create_req.email,\n\t\tpassword_hash: None,\n\t\tis_active: true,\n\t\tcreated_at: Utc::now(),\n\t};\n\n\t// Hash password using BaseUser trait\n\tuser.set_password(\u0026create_req.password)?;\n\n\t// Save to database using injected connection\n\tuser.save(\u0026db).await?;\n\n\t// Convert to response\n\tlet response_data = UserResponse::from(user);\n\tlet json = serde_json::to_string(\u0026response_data)?;\n\n\tOk(Response::new(StatusCode::CREATED)\n\t\t.with_body(json))\n}\n```\n\n## Available Components\n\nReinhardt offers modular components you can mix and match:\n\n| Component           | Crate Name                | Features                                    |\n|---------------------|---------------------------|---------------------------------------------|\n| **Core**            |                           |                                             |\n| Core Types          | `reinhardt-core`          | Core traits, types, macros (Model, endpoint)|\n| HTTP \u0026 Routing      | `reinhardt-http`          | Request/Response, HTTP handling             |\n| URL Routing         | `reinhardt-urls`          | Function-based and class-based routes       |\n| Server              | `reinhardt-server`        | HTTP server implementation                  |\n| Middleware          | `reinhardt-dispatch`      | Middleware chain, signal dispatch           |\n| Configuration       | `reinhardt-conf`          | Settings management, environment loading    |\n| Commands            | `reinhardt-commands`      | Management CLI tools (startproject, etc.)   |\n| Shortcuts           | `reinhardt-shortcuts`     | Common utility functions                    |\n| **Database**        |                           |                                             |\n| ORM                 | `reinhardt-db`            | reinhardt-query integration                |\n| **Authentication**  |                           |                                             |\n| Auth                | `reinhardt-auth`          | JWT, Token, Session, Basic auth, User models|\n| **REST API**        |                           |                                             |\n| Serializers         | `reinhardt-rest`          | serde/validator integration, ViewSets       |\n| **Forms**           |                           |                                             |\n| Forms               | `reinhardt-forms`         | Form handling and validation                |\n| **Advanced**        |                           |                                             |\n| Admin Panel         | `reinhardt-admin`         | Django-style admin interface                |\n| Plugin System       | `reinhardt-dentdelion`    | Static \u0026 WASM plugin support, CLI management|\n| Background Tasks    | `reinhardt-tasks`         | Task queues (Redis, RabbitMQ, SQLite)       |\n| GraphQL             | `reinhardt-graphql`       | Schema generation, subscriptions            |\n| WebSockets          | `reinhardt-websockets`    | Real-time communication                     |\n| i18n                | `reinhardt-i18n`          | Multi-language support                      |\n| **Testing**         |                           |                                             |\n| Test Utilities      | `reinhardt-test`          | Testing helpers, fixtures, TestContainers   |\n\n**For detailed feature flags within each crate, see the [Feature Flags Guide](https://reinhardt-web.dev/docs/feature-flags/).**\n\n---\n\n## Documentation\n\n- 📚 [Getting Started Guide](https://reinhardt-web.dev/quickstart/getting-started/) - Step-by-step tutorial for beginners\n- 🎛️ [Feature Flags Guide](https://reinhardt-web.dev/docs/feature-flags/) - Optimize your build with granular feature control\n- 📖 [API Reference](https://docs.rs/reinhardt) (Coming soon)\n- 📝 [Tutorials](https://reinhardt-web.dev/quickstart/tutorials/) - Learn by building real applications\n\n**For AI Assistants**: See [CLAUDE.md](CLAUDE.md) for project-specific coding standards, testing guidelines, and development conventions.\n\n## 💬 Getting Help\n\nReinhardt is a community-driven project. Here's where you can get help:\n\n- 💬 **Discord**: Join our Discord server for real-time chat (coming soon)\n- 💭 **GitHub Discussions**: [Ask questions and share ideas](https://github.com/kent8192/reinhardt-web/discussions)\n- 🐛 **Issues**: [Report bugs](https://github.com/kent8192/reinhardt-web/issues)\n- 📖 **Documentation**: [Read the guides](docs/)\n\nBefore asking, please check:\n\n- ✅ [Getting Started Guide](https://reinhardt-web.dev/quickstart/getting-started/)\n- ✅ [Examples](examples/)\n- ✅ Existing GitHub Issues and Discussions\n\n## 🤝 Contributing\n\nWe love contributions! Please read our [Contributing Guide](CONTRIBUTING.md) to get started.\n\n**Quick links**:\n\n- [Development Setup](CONTRIBUTING.md#development-setup)\n- [Testing Guidelines](CONTRIBUTING.md#testing-guidelines)\n- [Commit Guidelines](CONTRIBUTING.md#commit-guidelines)\n\n## ⭐ Star History\n\n\u003ca href=\"https://star-history.com/#kent8192/reinhardt-web\u0026Date\"\u003e\n \u003cpicture\u003e\n   \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"https://api.star-history.com/svg?repos=kent8192/reinhardt-web\u0026type=Date\u0026theme=dark\" /\u003e\n   \u003csource media=\"(prefers-color-scheme: light)\" srcset=\"https://api.star-history.com/svg?repos=kent8192/reinhardt-web\u0026type=Date\" /\u003e\n   \u003cimg alt=\"Star History Chart\" src=\"https://api.star-history.com/svg?repos=kent8192/reinhardt-web\u0026type=Date\" width=\"600\" /\u003e\n \u003c/picture\u003e\n\u003c/a\u003e\n\n## Copyright\n\nCopyright © 2026 Tachyon Inc. All rights reserved.\n\nDeveloped by Tachyon Inc.\n\n## License\n\nThis project is licensed under the [BSD 3-Clause License](LICENSE).\n\n### Third-Party Attribution\n\nThis project is inspired by:\n\n- [Django](https://www.djangoproject.com/) (BSD 3-Clause License)\n- [Django REST Framework](https://www.django-rest-framework.org/) (BSD 3-Clause License)\n- [FastAPI](https://fastapi.tiangolo.com/) (MIT License)\n- [SQLAlchemy](https://www.sqlalchemy.org/) (MIT License)\n\nSee [THIRD-PARTY-NOTICES](THIRD-PARTY-NOTICES) for full attribution.\n\n**Note:** This project is not affiliated with or endorsed by the Django Software Foundation, Encode OSS Ltd., Sebastián Ramírez (FastAPI author), or Michael Bayer (SQLAlchemy author).","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkent8192%2Freinhardt-web","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkent8192%2Freinhardt-web","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkent8192%2Freinhardt-web/lists"}