### Complete Example: Blog Setup Source: https://oxyde.fatalyst.dev/latest/guide/relations A comprehensive example demonstrating the setup of `Author` and `Post` models, including creating records, performing joins, and prefetching related data. ```APIDOC ## Complete Example ### Description This example sets up a simple blog structure with `Author` and `Post` models, demonstrating model definition, database connection, record creation, and querying with `join` and `prefetch`. ### Method N/A (Model Definition & Async Operations) ### Endpoint N/A (Model Definition & Async Operations) ### Parameters N/A (Model Definition & Async Operations) ### Request Example N/A (Model Definition & Async Operations) ### Response N/A (Model Definition & Async Operations) ### Code Example ```python from datetime import datetime from oxyde import Model, Field, db class Author(Model): id: int | None = Field(default=None, db_pk=True) name: str posts: list["Post"] = Field(db_reverse_fk="author") class Meta: is_table = True table_name = "authors" class Post(Model): id: int | None = Field(default=None, db_pk=True) title: str content: str author: Author | None = Field(default=None, db_on_delete="CASCADE") created_at: datetime = Field(db_default="CURRENT_TIMESTAMP") class Meta: is_table = True table_name = "posts" async def main(): async with db.connect("sqlite:///blog.db"): # Create author author = await Author.objects.create(name="Alice") # Create posts await Post.objects.create( title="First Post", content="Hello!", author_id=author.id ) await Post.objects.create( title="Second Post", content="World!", author_id=author.id ) # Load posts with author (JOIN) posts = await Post.objects.join("author").all() for post in posts: print(f"{post.title} by {post.author.name}") # Load author with posts (prefetch) authors = await Author.objects.prefetch("posts").all() for author in authors: print(f"{author.name}: {len(author.posts)} posts") ``` ``` -------------------------------- ### Complete Oxyde ORM Example: Blog Setup Source: https://oxyde.fatalyst.dev/latest/guide/relations A comprehensive example demonstrating the setup of `Author` and `Post` models with relationships, database connection, data creation, and querying using joins and prefetches. ```python from datetime import datetime from oxyde import Model, Field, db class Author(Model): id: int | None = Field(default=None, db_pk=True) name: str posts: list["Post"] = Field(db_reverse_fk="author") class Meta: is_table = True table_name = "authors" class Post(Model): id: int | None = Field(default=None, db_pk=True) title: str content: str author: Author | None = Field(default=None, db_on_delete="CASCADE") created_at: datetime = Field(db_default="CURRENT_TIMESTAMP") class Meta: is_table = True table_name = "posts" async def main(): async with db.connect("sqlite:///blog.db"): # Create author author = await Author.objects.create(name="Alice") # Create posts await Post.objects.create( title="First Post", content="Hello!", author_id=author.id ) await Post.objects.create( title="Second Post", content="World!", author_id=author.id ) # Load posts with author (JOIN) posts = await Post.objects.join("author").all() for post in posts: print(f"{post.title} by {post.author.name}") # Load author with posts (prefetch) authors = await Author.objects.prefetch("posts").all() for author in authors: print(f"{author.name}: {len(author.posts)} posts") ``` -------------------------------- ### Install Dependencies Source: https://oxyde.fatalyst.dev/latest/getting-started/fastapi-project Installs the necessary libraries: Oxyde for ORM, FastAPI for the web framework, and Uvicorn for the ASGI server. ```bash pip install oxyde fastapi uvicorn ``` -------------------------------- ### Install and Initialize Oxyde Source: https://oxyde.fatalyst.dev/latest/getting-started/quickstart Instructions for installing the Oxyde package and initializing the project configuration. This process generates the necessary configuration file for database connectivity. ```bash pip install oxyde oxyde init ``` -------------------------------- ### FastAPI Application Setup (Python) Source: https://oxyde.fatalyst.dev/latest/getting-started/fastapi-project Initializes a FastAPI application, configuring the database lifespan using Oxyde's `db.lifespan` and including the application router. ```python # main.py from fastapi import FastAPI from oxyde import db from routes import router app = FastAPI( lifespan=db.lifespan(default="sqlite:///app.db") ) app.include_router(router) ``` -------------------------------- ### Error Handling Example Source: https://oxyde.fatalyst.dev/latest/guide/connections Illustrates how to handle potential connection errors during database initialization. ```APIDOC ## Error Handling ### Description Provides an example of catching exceptions that may occur during database initialization, such as invalid connection strings. ### Method N/A (Code example) ### Endpoint N/A ### Parameters N/A ### Request Example ```python from oxyde import db from oxyde.exceptions import ManagerError try: await db.init(default="postgresql://invalid-host/db") except Exception as e: print(f"Connection failed: {e}") ``` ### Response N/A ``` -------------------------------- ### Complete Oxyde ORM Model Example Source: https://oxyde.fatalyst.dev/latest/guide/fields Provides a comprehensive example of an Oxyde ORM model (`Product`), showcasing various field types, validation rules, default values, SQL defaults, foreign key relationships, and table metadata. ```python from datetime import datetime from decimal import Decimal from uuid import UUID, uuid4 from oxyde import Model, Field class Product(Model): # Primary key id: UUID = Field(default_factory=uuid4, db_pk=True) # Required fields name: str = Field(min_length=1, max_length=200) price: Decimal = Field(ge=0, db_type="NUMERIC(10, 2)") # Optional fields description: str | None = Field(default=None) sku: str | None = Field(default=None, db_unique=True, db_index=True) # With defaults active: bool = Field(default=True) stock: int = Field(default=0, ge=0) # SQL defaults created_at: datetime = Field(db_default="CURRENT_TIMESTAMP") updated_at: datetime | None = Field(default=None) # Foreign key category: Category | None = Field(default=None, db_on_delete="SET NULL") class Meta: is_table = True table_name = "products" ``` -------------------------------- ### Quick Start: Initialize, Use, and Close Database Connection Source: https://oxyde.fatalyst.dev/latest/guide/connections Demonstrates the basic workflow for initializing a database connection, performing operations using models, and gracefully closing the connection. Requires the 'oxyde' library. ```python from oxyde import db # Initialize await db.init(default="postgresql://localhost/mydb") # Use models users = await User.objects.all() # Close await db.close() ``` -------------------------------- ### Run FastAPI Application (Bash) Source: https://oxyde.fatalyst.dev/latest/getting-started/fastapi-project Starts the FastAPI application using Uvicorn, enabling hot-reloading for development. ```bash uvicorn main:app --reload ``` -------------------------------- ### ON DELETE Action Examples for Foreign Keys Source: https://oxyde.fatalyst.dev/latest/guide/fields Illustrates the different ON DELETE actions available for foreign keys (CASCADE, SET NULL, RESTRICT) and their impact on related data. ```python # CASCADE - delete posts when author is deleted author: Author | None = Field(default=None, db_on_delete="CASCADE") # SET NULL - set author_id to NULL when author is deleted author: Author | None = Field(default=None, db_on_delete="SET NULL") # RESTRICT - prevent author deletion if posts exist author: Author | None = Field(default=None, db_on_delete="RESTRICT") ``` -------------------------------- ### Build Oxyde from source Source: https://oxyde.fatalyst.dev/latest/faq Builds and installs Oxyde from its source code. This process involves cloning the repository, installing Rust if necessary, and then using maturin to build the Rust core and install the Python package. ```bash # Clone repository git clone https://github.com/mr-fatalyst/oxyde.git cd oxyde # Install Rust (if not installed) curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh # Build and install cd crates/oxyde-core-py maturin develop --release cd ../../python pip install -e . ``` -------------------------------- ### Configuring Read Replicas Source: https://oxyde.fatalyst.dev/latest/guide/connections Shows how to initialize database connections with a primary and a replica. This setup allows read operations to be directed to the replica for performance, while write operations are sent to the primary database, ensuring data consistency. ```python await db.init( default="postgresql://primary/db", replica="postgresql://replica/db", ) async def get_user(user_id: int): # Read from replica return await User.objects.get(id=user_id, using="replica") async def update_user(user_id: int, **data): # Write to primary await User.objects.filter(id=user_id).update(**data) ``` -------------------------------- ### Per-Database Connection Settings Source: https://oxyde.fatalyst.dev/latest/guide/connections Illustrates how to configure distinct `PoolSettings` for multiple databases. This example shows setting up a 'default' high-concurrency PostgreSQL database and an 'analytics' database optimized for read-heavy workloads with fewer connections. ```python from oxyde import AsyncDatabase, PoolSettings # Main database: high concurrency main_db = AsyncDatabase( "postgresql://localhost/main", name="default", settings=PoolSettings( max_connections=50, min_connections=10, ), ) # Analytics: read-heavy, fewer connections analytics_db = AsyncDatabase( "postgresql://localhost/analytics", name="analytics", settings=PoolSettings( max_connections=10, min_connections=2, ), ) await main_db.connect() await analytics_db.connect() ``` -------------------------------- ### Atomic Money Transfer Example Source: https://oxyde.fatalyst.dev/latest/guide/transactions A comprehensive example demonstrating an atomic money transfer between two accounts, utilizing row-level locking and error handling to ensure consistency. ```python async def transfer(from_id: int, to_id: int, amount: float) -> bool: try: async with transaction.atomic(timeout=30): from_acc = await Account.objects.filter(id=from_id).for_update().first() to_acc = await Account.objects.filter(id=to_id).for_update().first() if not from_acc or not to_acc or from_acc.balance < amount: return False await Account.objects.filter(id=from_id).update(balance=F("balance") - amount) await Account.objects.filter(id=to_id).update(balance=F("balance") + amount) return True except TransactionTimeoutError: return False ``` -------------------------------- ### Example Python Query to IR Conversion Source: https://oxyde.fatalyst.dev/latest/advanced/internals Illustrates a Python query syntax and its conceptual translation into an Intermediate Representation (IR) that Oxyde can process. This highlights the input format for query execution. ```python # Python query User.objects.filter(age__gte=18, status="active").order_by("-created_at").limit(10) ``` -------------------------------- ### Relations Source: https://oxyde.fatalyst.dev/latest/guide/fields This section is intended for documenting relation parameters, but no specific examples were provided in the input text. ```APIDOC ## Relations ### Description This section covers the configuration of various relation types, including many-to-many relationships, using parameters like `db_reverse_fk`, `db_m2m`, and `db_through`. ### Parameters #### Relation Parameters - **db_reverse_fk** (str) - Optional - Reverse FK field name - **db_m2m** (bool) - Optional - Many-to-many relation - **db_through** (str) - Optional - M2M junction table ### Example Usage (No specific examples provided in the source text for relations.) ``` -------------------------------- ### Testing with Multiple Databases Source: https://oxyde.fatalyst.dev/latest/guide/connections Provides an example of setting up multiple in-memory SQLite databases for testing purposes using pytest fixtures. ```APIDOC ### Testing with Multiple Databases #### Description Demonstrates how to configure and use multiple databases within a testing environment, specifically using pytest and in-memory SQLite databases. #### Method N/A (Code example) #### Endpoint N/A #### Parameters N/A #### Request Example ```python import pytest @pytest.fixture async def test_dbs(): await db.init( default="sqlite:///:memory:", analytics="sqlite:///:memory:", ) yield await db.close() @pytest.mark.asyncio async def test_cross_db(test_dbs): user = await User.objects.create(name="Test") await Event.objects.create( type="test", user_id=user.id, using="analytics" ) events = await Event.objects.filter(user_id=user.id).all(using="analytics") assert len(events) == 1 ``` #### Response N/A ``` -------------------------------- ### Specifying Index Methods in Oxyde (PostgreSQL) Source: https://oxyde.fatalyst.dev/latest/guide/models Provides examples of specifying different index methods like GIN and Hash for PostgreSQL databases within Oxyde's `Index` definition. ```Python Index(("data",), method="gin") # GIN index for JSONB Index(("name",), method="hash") # Hash index for equality ``` -------------------------------- ### FastAPI with Multiple Databases Configuration Source: https://oxyde.fatalyst.dev/latest/guide/connections Shows how to configure a FastAPI application to use multiple databases via the `lifespan` parameter. This example sets up 'default' and 'analytics' databases, and demonstrates how to specify the database to use for different API endpoints. ```python from fastapi import FastAPI, Depends, Request from oxyde import db, PoolSettings app = FastAPI( lifespan=db.lifespan( default="postgresql://localhost/main", analytics="postgresql://localhost/analytics", settings=PoolSettings(max_connections=20), ) ) @app.get("/users") async def get_users(): return await User.objects.all() @app.get("/events") async def get_events(): return await Event.objects.all(using="analytics") ``` -------------------------------- ### Python: Data Creation Operations Source: https://oxyde.fatalyst.dev/latest/cheatsheet Shows different methods for creating data, including simple object creation, getting or creating a record if it doesn't exist, and efficiently creating multiple records in bulk. ```python # Simple create user = await User.objects.create(name="John", age=25) # Get or create user, created = await User.objects.get_or_create( email="test@test.com", defaults={"name": "John", "age": 25} ) # Bulk create users = await User.objects.bulk_create([ User(name="John", age=25), User(name="Jane", age=30), ]) ``` -------------------------------- ### Configuring Lifespan for Web Apps Source: https://oxyde.fatalyst.dev/latest/guide/connections Demonstrates how to integrate Oxyde's database connection management with FastAPI applications using the `lifespan` parameter. This ensures that database connections are initialized when the application starts and closed gracefully when it shuts down. ```python app = FastAPI(lifespan=db.lifespan(default="postgresql://...")) ``` -------------------------------- ### Perform Aggregation and Grouping with Oxyde ORM Source: https://oxyde.fatalyst.dev/latest/guide/aggregation This example demonstrates how to define a model, connect to a database, and perform advanced queries such as counting records, summing values, and grouping results by specific columns. It utilizes asynchronous patterns to handle database operations efficiently. ```python import asyncio from oxyde import Model, Field, db, Count, Sum, Avg class Order(Model): class Meta: is_table = True id: int | None = Field(default=None, db_pk=True) customer_id: int amount: float status: str async def main(): async with db.connect("sqlite:///orders.db"): # Total orders and revenue total_orders = await Order.objects.count() total_revenue = await Order.objects.sum("amount") print(f"Orders: {total_orders}, Revenue: ${total_revenue}") # Revenue by status by_status = await Order.objects.values("status").annotate( count=Count("*"), total=Sum("amount") ).group_by("status").all() for row in by_status: print(f"{row['status']}: {row['count']} orders, ${row['total']}") # Top customers top = await Order.objects.values("customer_id").annotate( orders=Count("*"), spent=Sum("amount") ).group_by("customer_id").order_by("-spent").limit(5).all() print("\nTop customers:") for row in top: print(f"Customer {row['customer_id']}: ${row['spent']}") asyncio.run(main()) ``` -------------------------------- ### Explain Query Plans (Python) Source: https://oxyde.fatalyst.dev/latest/advanced/performance Shows how to use the `.explain()` method to retrieve and analyze the query execution plan, helping to identify performance bottlenecks like sequential scans that may require indexing. ```Python # Get query plan plan = await User.objects.filter(age__gte=18).explain() print(plan) # With execution times plan = await User.objects.filter(age__gte=18).explain(analyze=True) print(plan) ``` -------------------------------- ### Install Oxyde ORM Source: https://oxyde.fatalyst.dev/latest Provides the command to install the oxyde-admin package, which is part of the Oxyde ORM ecosystem for auto-generating admin panels. ```bash pip install oxyde-admin ``` -------------------------------- ### Install Oxyde using pip Source: https://oxyde.fatalyst.dev/latest/faq Installs the Oxyde ORM package using pip. This is the standard method for adding Oxyde to your Python project. ```bash pip install oxyde ``` -------------------------------- ### Initialize Oxyde Project Source: https://oxyde.fatalyst.dev/latest/getting-started/first-project Commands to create a new project directory and initialize the Oxyde environment with specific database configurations. ```bash mkdir blog && cd blog oxyde init ``` -------------------------------- ### Initialize Multiple Database Connections Source: https://oxyde.fatalyst.dev/latest/guide/connections Illustrates how to initialize multiple named database connections simultaneously, specifying different connection URLs for each. ```python from oxyde import db, PoolSettings # Single database await db.init(default="postgresql://localhost/mydb") # Multiple databases await db.init( default="postgresql://localhost/main", analytics="postgresql://localhost/analytics", cache="sqlite:///:memory:", ) # With custom settings await db.init( default="postgresql://localhost/mydb", settings=PoolSettings(max_connections=20), ) ``` -------------------------------- ### Advanced: Multiple Databases - Read Replicas Source: https://oxyde.fatalyst.dev/latest/guide/connections Demonstrates setting up a primary database and read replicas, and how to direct read/write operations to the appropriate database. ```APIDOC ### Read Replicas #### Description Configures a primary database for writes and one or more replicas for reads, allowing for scalable read operations. #### Method N/A (Code example) #### Endpoint N/A #### Parameters N/A #### Request Example ```python await db.init( default="postgresql://primary/db", replica="postgresql://replica/db", ) async def get_user(user_id: int): # Read from replica return await User.objects.get(id=user_id, using="replica") async def update_user(user_id: int, **data): # Write to primary await User.objects.filter(id=user_id).update(**data) ``` #### Response N/A ``` -------------------------------- ### Building from Source Source: https://oxyde.fatalyst.dev/latest/advanced/internals Provides commands for building the project from source, including building all crates, the Python extension, and running tests. ```APIDOC ## Building from Source Commands to build the project and its components. ### Build All Crates ```bash # Build all crates cargo build --release ``` ### Build Python Extension ```bash # Build Python extension cd crates/oxyde-core-py maturin develop --release ``` ### Run Rust Tests ```bash # Run Rust tests cargo test --workspace ``` ### Run with Logging ```bash # Run with logging RUST_LOG=debug cargo test ``` ``` -------------------------------- ### Analyze Query Performance with Explain Source: https://oxyde.fatalyst.dev/latest/advanced/raw-queries Shows how to retrieve execution plans for both ORM queries and raw SQL statements to optimize database performance. ```python plan = await User.objects.filter(age__gte=18).explain(analyze=True) results = await execute_raw("EXPLAIN ANALYZE SELECT * FROM users WHERE age >= 18") ``` -------------------------------- ### Perform CRUD Operations with Oxyde Source: https://oxyde.fatalyst.dev/latest/getting-started/quickstart Examples of creating, reading, updating, and deleting records using the Oxyde ORM manager and instance methods. ```python # Create user = await User.objects.create(name="Alice", email="alice@example.com") # Read users = await User.objects.filter(age__gte=18).all() # Update user.name = "Alice Smith" await user.save() # Delete await user.delete() ``` -------------------------------- ### Specifying Database for Oxyde Transactions Source: https://oxyde.fatalyst.dev/latest/guide/transactions Illustrates how to use transactions on a specific database by providing the `using` argument to `transaction.atomic()`. This is useful in multi-database setups. ```python async with transaction.atomic(using="analytics"): await Event.objects.create(type="signup") ``` -------------------------------- ### Advanced SQL Patterns Source: https://oxyde.fatalyst.dev/latest/advanced/raw-queries Examples of complex SQL patterns including window functions, JSON operations, recursive CTEs, and bulk upsert operations. ```python # Window Functions results = await execute_raw("SELECT id, RANK() OVER (ORDER BY salary DESC) as rank FROM employees") # Recursive CTE results = await execute_raw("WITH RECURSIVE category_tree AS (...) SELECT * FROM category_tree") # Bulk Upsert sql = "INSERT INTO products (sku, name, price) VALUES ($1, $2, $3) ON CONFLICT (sku) DO UPDATE SET name = EXCLUDED.name" for product in products: await execute_raw(sql, [product.sku, product.name, product.price]) ``` -------------------------------- ### Manually Hydrate Models from Raw Queries Source: https://oxyde.fatalyst.dev/latest/advanced/raw-queries Explains that raw queries return dictionaries by default and demonstrates how to manually convert these results back into model instances. ```python rows = await execute_raw("SELECT * FROM users WHERE ...") users = [User.model_validate(row) for row in rows] ``` -------------------------------- ### Handling FieldLookupValueError in Python Source: https://oxyde.fatalyst.dev/latest/guide/exceptions Demonstrates catching `FieldLookupValueError`, which occurs when the value provided for a lookup is incompatible with the operator. Examples include incorrect types for `__in` or `__contains`. ```python try: await User.objects.filter(id__in="not_a_list").all() except FieldLookupValueError as e: print(f"Value error: {e}") # "Lookup 'in' does not accept string values; use a sequence" ``` ```python try: await User.objects.filter(age__gte=None).all() except FieldLookupValueError as e: print(f"Value error: {e}") # "Lookup 'gte' requires a non-null value" ``` ```python try: await User.objects.filter(age__between=(18,)).all() except FieldLookupValueError as e: print(f"Value error: {e}") # "Lookup 'between' requires a tuple/list of two values" ``` -------------------------------- ### Retrieving Single or Multiple Objects Source: https://oxyde.fatalyst.dev/latest/guide/queries Methods for fetching records from the database. Includes all() for collections, get() for single records with error handling, and get_or_none() for safe retrieval. ```python # Get all users = await User.objects.all() # Get one with error handling from oxyde.exceptions import NotFoundError, MultipleObjectsReturned try: user = await User.objects.get(id=1) except NotFoundError: print("User not found") except MultipleObjectsReturned: print("Multiple users found") # Get or none user = await User.objects.get_or_none(email="alice@example.com") ``` -------------------------------- ### Error Handling for Database Initialization Source: https://oxyde.fatalyst.dev/latest/guide/connections Illustrates how to handle potential exceptions during the initialization of a database connection. It shows a try-except block to catch errors, such as invalid connection strings or host issues, and print informative messages. ```python from oxyde import db from oxyde.exceptions import ManagerError try: await db.init(default="postgresql://invalid-host/db") except Exception as e: print(f"Connection failed: {e}") ``` -------------------------------- ### Define Migration Upgrade and Downgrade Logic Source: https://oxyde.fatalyst.dev/latest/guide/migrations Demonstrates how to structure a migration file with upgrade and downgrade functions. It uses the migration context to create tables and manage foreign key constraints. ```python # 0003_add_posts.py """Auto-generated migration. Created: 2024-01-15 11:00:00 """ depends_on = "0002_add_age" def upgrade(ctx): """Apply migration.""" ctx.create_table( "posts", fields=[ {"name": "id", "field_type": "INTEGER", "primary_key": True}, {"name": "title", "field_type": "TEXT", "nullable": False}, {"name": "author_id", "field_type": "INTEGER", "nullable": False}, ], ) ctx.add_foreign_key( "posts", "fk_posts_author", ["author_id"], "users", ["id"], on_delete="CASCADE", ) def downgrade(ctx): """Revert migration.""" ctx.drop_foreign_key("posts", "fk_posts_author") ctx.drop_table("posts") ``` -------------------------------- ### explain() - Query Performance Analysis Source: https://oxyde.fatalyst.dev/latest/advanced/raw-queries Shows how to use the `explain()` method for both ORM queries and raw SQL to analyze query performance and execution plans. ```APIDOC ## explain() - Query Performance Analysis Analyze query performance using the `explain()` method for both ORM queries and raw SQL. ### Method - `ORM: User.objects.filter(...).explain(analyze=True)` - `Raw SQL: execute_raw("EXPLAIN ANALYZE ...")` ### Description This feature helps in understanding how the database executes your queries, identifying bottlenecks, and optimizing performance. ### Request Example ```python # Using ORM explain plan = await User.objects.filter(age__gte=18).explain(analyze=True) # Raw SQL explain results = await execute_raw("EXPLAIN ANALYZE SELECT * FROM users WHERE age >= 18") ``` ``` -------------------------------- ### Retrieve Database Connection by Name Source: https://oxyde.fatalyst.dev/latest/guide/connections Shows how to get a specific database connection object from the connection registry using its registered name, allowing for direct interaction with the connection. ```python from oxyde import get_connection conn = await get_connection("default") print(conn.connected) # True ``` -------------------------------- ### Execute Raw SQL Queries Source: https://oxyde.fatalyst.dev/latest/advanced/raw-queries Demonstrates how to execute raw SQL queries using execute_raw, including connection resolution and transaction support. ```python from oxyde import execute_raw, transaction # Simple SELECT users = await execute_raw("SELECT * FROM users WHERE age > $1", [18]) # Connection resolution examples results = await execute_raw("SELECT * FROM users") results = await execute_raw("SELECT * FROM metrics", using="analytics") # Transactional execution async with transaction.atomic(): await execute_raw("INSERT INTO audit_log (user_id, action) VALUES ($1, $2)", [1, "created"]) ``` -------------------------------- ### Build and Test Project Source: https://oxyde.fatalyst.dev/latest/advanced/internals Shell commands for building the Rust crates, compiling the Python extension, and running the test suite. ```bash cargo build --release cd crates/oxyde-core-py maturin develop --release cargo test --workspace RUST_LOG=debug cargo test ``` -------------------------------- ### Optimize Transaction Scope Source: https://oxyde.fatalyst.dev/latest/guide/transactions Provides examples of keeping transactions short by avoiding external calls like network requests inside atomic blocks and avoiding unnecessary nested transactions. ```python # GOOD: Short transaction async with transaction.atomic(): user = await User.objects.get(id=1) user.status = "active" await user.save() # BAD: Long transaction with external calls async with transaction.atomic(): user = await User.objects.get(id=1) await send_email(user) user.notified = True await user.save() # GOOD: Single transaction async with transaction.atomic(): await create_user() await create_profile() ``` -------------------------------- ### Create and Query Data with Oxyde ORM in Python Source: https://oxyde.fatalyst.dev/latest/getting-started/first-project This Python script initializes the Oxyde ORM, creates sample blog data (authors, posts, tags), and demonstrates various query patterns like filtering, ordering, updating with F expressions, and retrieving specific data. It also shows how to perform aggregate operations like count, sum, and average. ```python import asyncio from oxyde import db, F, Q from models import Author, Post, Tag async def main(): # Connect to database await db.init(default="sqlite:///blog.db") try: # Create sample data await create_sample_data() # Run queries await demo_queries() # Show statistics await show_stats() finally: await db.close() async def create_sample_data(): """Create authors, posts, and tags.""" print("Creating sample data...") # Create authors alice = await Author.objects.create( name="Alice Johnson", email="alice@example.com", bio="Python developer and tech writer" ) bob = await Author.objects.create( name="Bob Smith", email="bob@example.com", bio="Backend engineer" ) # Create posts await Post.objects.create( title="Getting Started with Oxyde", content="Oxyde is a high-performance async ORM...", published=True, author_id=alice.id ) await Post.objects.create( title="Advanced Query Patterns", content="In this post, we explore advanced queries...", published=True, views=150, author_id=alice.id ) await Post.objects.create( title="Draft: Performance Tips", content="Work in progress...", published=False, author_id=bob.id ) # Create tags for name in ["python", "orm", "async", "tutorial"]: await Tag.objects.create(name=name) print("Sample data created!\n") async def demo_queries(): """Demonstrate various query patterns.""" print("=== Query Examples ===\n") # Basic filtering published = await Post.objects.filter(published=True).all() print(f"Published posts: {len(published)}") # Multiple conditions with Q popular = await Post.objects.filter( Q(published=True) & Q(views__gte=100) ).all() print(f"Popular posts (100+ views): {len(popular)}") # Ordering and limiting recent = await Post.objects.filter( published=True ).order_by("-created_at").limit(5).all() print(f"Recent posts: {[p.title for p in recent]}") # Get single record author = await Author.objects.get(email="alice@example.com") print(f"Found author: {author.name}") # Update with F expression (atomic increment) await Post.objects.filter(title__contains="Oxyde").update( views=F("views") + 1 ) print("Incremented views for Oxyde posts") # Values (return dicts instead of models) emails = await Author.objects.values("name", "email").all() print(f"Author emails: {emails}") # Exists check has_drafts = await Post.objects.filter(published=False).exists() print(f"Has draft posts: {has_drafts}") print() async def show_stats(): """Show aggregate statistics.""" print("=== Statistics ===\n") # Count total_posts = await Post.objects.count() print(f"Total posts: {total_posts}") # Sum total_views = await Post.objects.sum("views") print(f"Total views: {total_views}") # Average avg_views = await Post.objects.avg("views") print(f"Average views: {avg_views:.1f}") # Count with filter published_count = await Post.objects.filter(published=True).count() print(f"Published posts: {published_count}") if __name__ == "__main__": asyncio.run(main()) ``` -------------------------------- ### Conditional Rollback for Order Processing with Oxyde Source: https://oxyde.fatalyst.dev/latest/guide/transactions An example of processing an order and conditionally rolling back the transaction if the order status is not 'pending'. Uses `tx.set_rollback(True)` to mark the transaction for rollback. ```python async def process_order(order_id: int): async with transaction.atomic() as tx: order = await Order.objects.get(id=order_id) if order.status != "pending": tx.set_rollback(True) return None await order.process() order.status = "completed" await order.save() return order ``` -------------------------------- ### Define Database Models Source: https://oxyde.fatalyst.dev/latest/guide/migrations Example of defining database models using Oxyde's Model and Field classes, including primary keys, unique constraints, and foreign key relationships. ```python from datetime import datetime from oxyde import Model, Field, Index class User(Model): id: int | None = Field(default=None, db_pk=True) email: str = Field(db_unique=True) name: str created_at: datetime = Field(db_default="CURRENT_TIMESTAMP") class Meta: is_table = True table_name = "users" class Post(Model): id: int | None = Field(default=None, db_pk=True) title: str content: str author: User | None = Field(default=None, db_on_delete="CASCADE") created_at: datetime = Field(db_default="CURRENT_TIMESTAMP") class Meta: is_table = True table_name = "posts" indexes = [ Index(("author_id", "created_at")), ] ``` -------------------------------- ### Create, Update, and Delete Database Records Source: https://oxyde.fatalyst.dev/latest/guide/models Demonstrates how to insert, update, and delete records in the database using the User model. Includes saving a new user, updating an existing one, performing partial updates, and deleting a record by its ID. ```python user = User(name="Alice", email="alice@example.com") await user.save() print(user.id) # Auto-generated ID user.name = "Alice Smith" await user.save() user.age = 31 await user.save(update_fields=["age"]) user = await User.objects.get(id=1) await user.delete() ``` -------------------------------- ### Custom SQL Type Overrides Source: https://oxyde.fatalyst.dev/latest/guide/fields Explains how to override the inferred SQL data types for fields using the `db_type` parameter, including examples for VARCHAR, JSONB, TEXT arrays, and LONGTEXT. ```python # Override inferred type name: str = Field(db_type="VARCHAR(255)") # PostgreSQL-specific data: dict = Field(db_type="JSONB") tags: list[str] = Field(db_type="TEXT[]") # MySQL-specific content: str = Field(db_type="LONGTEXT") ``` -------------------------------- ### Query Builder Pattern and Execution Source: https://oxyde.fatalyst.dev/latest/guide/queries Demonstrates how to build a query by chaining methods and executing it using terminal methods like all(). The query remains unexecuted until a terminal method is called. ```python # Build query (not executed yet) query = User.objects.filter(status="active").order_by("-created_at").limit(10) # Execute query users = await query.all() ``` -------------------------------- ### Handling MultipleObjectsReturned in Python Source: https://oxyde.fatalyst.dev/latest/guide/exceptions Shows how to catch `MultipleObjectsReturned`, raised when a query expecting a single row (like `get()`) finds more than one matching record. It suggests using unique fields to prevent this. ```python try: user = await User.objects.get(status="active") # Many active users! except MultipleObjectsReturned as e: print(f"Multiple found: {e}") # "Query for User returned multiple objects" ``` ```python # Use unique fields for get() user = await User.objects.get(email="alice@example.com") ``` -------------------------------- ### Best Practice: Set Appropriate Timeouts Source: https://oxyde.fatalyst.dev/latest/guide/connections Recommends configuring connection timeouts (`acquire_timeout`, `idle_timeout`, `max_lifetime`) for production environments. ```APIDOC ### 4. Set Appropriate Timeouts #### Description Manages database connection resources effectively by setting timeouts for acquiring connections, idle connections, and maximum connection lifetime. #### Method N/A (Code example) #### Endpoint N/A #### Parameters N/A #### Request Example ```python # Production PoolSettings( acquire_timeout=30, # Don't wait forever idle_timeout=300, # Close idle after 5 min max_lifetime=3600, # Refresh connections hourly ) ``` #### Response N/A ``` -------------------------------- ### Using Context Managers for Scripts Source: https://oxyde.fatalyst.dev/latest/guide/connections Shows the recommended way to manage database connections within asynchronous scripts using context managers. The `async with db.connect(...)` syntax ensures that the database connection is automatically established and properly cleaned up upon exiting the block. ```python async def main(): async with db.connect("sqlite:///app.db"): # Automatic cleanup on exit await run_app() ``` -------------------------------- ### Abstract Model Inheritance Source: https://oxyde.fatalyst.dev/latest/guide/models Demonstrates how to use abstract models for code reuse without creating separate database tables. The TimestampMixin is an example of an abstract model that can be inherited by concrete models like User. ```python class TimestampMixin(Model): """Mixin for created_at/updated_at fields.""" created_at: datetime = Field(db_default="CURRENT_TIMESTAMP") updated_at: datetime | None = Field(default=None) class User(TimestampMixin): id: int | None = Field(default=None, db_pk=True) name: str class Meta: is_table = True ``` -------------------------------- ### Configure SQLite Specific Pool Settings Source: https://oxyde.fatalyst.dev/latest/guide/connections Demonstrates how to configure SQLite-specific PRAGMA settings within `PoolSettings` to optimize performance and behavior, such as WAL mode and synchronous writes. ```python settings = PoolSettings( # WAL mode for better concurrent writes (10-20x faster) sqlite_journal_mode="WAL", # Balance between speed and safety sqlite_synchronous="NORMAL", # Cache size in pages (~10MB) sqlite_cache_size=10000, # Lock timeout in milliseconds sqlite_busy_timeout=5000, ) ``` -------------------------------- ### Customizing SQL Types in Oxyde Models Source: https://oxyde.fatalyst.dev/latest/guide/models Illustrates how to override the inferred SQL data type for a model field using the `db_type` argument. Examples include specifying `BIGSERIAL`, `VARCHAR(255)`, and `JSONB`. ```Python class User(Model): id: int = Field(db_pk=True, db_type="BIGSERIAL") name: str = Field(db_type="VARCHAR(255)") data: dict = Field(db_type="JSONB") # PostgreSQL class Meta: is_table = True ``` -------------------------------- ### Configure Multiple Databases for Oxyde Source: https://oxyde.fatalyst.dev/latest/guide/connections Shows how to configure multiple named database connections during initialization, allowing the application to connect to different databases simultaneously. ```python await db.init( default="postgresql://localhost/main", analytics="postgresql://localhost/analytics", legacy="mysql://localhost/old_system", ) ``` -------------------------------- ### Override SQLite Settings for Safety or Speed (Python) Source: https://oxyde.fatalyst.dev/latest/advanced/performance Provides examples of overriding default SQLite settings to prioritize maximum safety (at the cost of speed) or maximum speed (with reduced safety against power failures). ```Python # Maximum safety (slower) PoolSettings( sqlite_journal_mode="DELETE", sqlite_synchronous="FULL", ) # Maximum speed (less safe for power failure) PoolSettings( sqlite_synchronous="OFF", sqlite_cache_size=50000, # 50MB cache ) ``` -------------------------------- ### SQL Default Value Configuration Source: https://oxyde.fatalyst.dev/latest/guide/fields Provides examples of setting SQL DEFAULT values for fields using Field(), including timestamps, database functions like gen_random_uuid(), string literals, and numeric defaults. ```python # Timestamp created_at: datetime = Field(db_default="CURRENT_TIMESTAMP") # PostgreSQL functions uuid: str = Field(db_default="gen_random_uuid()") # String literal (note the quotes) status: str = Field(db_default="'pending'") # Numeric count: int = Field(db_default="0") ``` -------------------------------- ### Configure Connection Pool Size (Python) Source: https://oxyde.fatalyst.dev/latest/advanced/performance Demonstrates how to configure the connection pool size using `PoolSettings` based on application workload, such as web APIs requiring many connections or background workers needing fewer. ```Python from oxyde import PoolSettings # Web API: many concurrent connections settings = PoolSettings( max_connections=50, min_connections=10, ) # Background worker: fewer long-lived connections settings = PoolSettings( max_connections=10, min_connections=2, ) # SQLite: limited concurrency settings = PoolSettings( max_connections=5, # SQLite handles this well with WAL ) ``` -------------------------------- ### Manage Database Migrations via CLI Source: https://oxyde.fatalyst.dev/latest/faq Common command-line interface commands for creating, applying, inspecting, and rolling back database schema migrations. ```bash oxyde makemigrations oxyde migrate oxyde showmigrations oxyde migrate 0001 ``` -------------------------------- ### Project Structure Overview Source: https://oxyde.fatalyst.dev/latest/getting-started/fastapi-project Illustrates a typical project layout for an application using Oxyde and FastAPI, organizing code into main application logic, models, and routes. ```text myapp/ ├── main.py ├── models.py └── routes.py ``` -------------------------------- ### Group By Guards Model Hydration in Python Source: https://oxyde.fatalyst.dev/latest/changelog Calling `.all()` on a `group_by()` query now raises a `TypeError` with a clear message, guiding users to use `.values()` or `.fetch_all()` instead to prevent incorrect model hydration. ```python # Calling .all() on group_by() query now raises TypeError # Use .values() or .fetch_all() instead ``` -------------------------------- ### Oxyde Type Annotations: Direct Reference Source: https://oxyde.fatalyst.dev/latest/guide/relations Example showing how to use direct type annotations for foreign keys when the target model is defined before the referencing model. This is the straightforward approach when model definition order allows. ```python class Author(Model): ... class Post(Model): author: Author | None = Field(default=None, db_on_delete="CASCADE") # ✓ Author is defined above ``` -------------------------------- ### Python: Basic Query Operations Source: https://oxyde.fatalyst.dev/latest/cheatsheet Demonstrates fundamental query operations like filtering, prefetching related data, ordering, limiting results, joining foreign keys, and retrieving single objects. ```python # Simple query users = await User.objects.filter(is_active=True, age__gte=18).all() # With prefetch and ordering users = await User.objects \ .prefetch("posts") \ .filter(is_active=True) \ .order_by("-created_at") \ .limit(10) \ .all() # Join for FK posts = await Post.objects.join("author").filter(status="draft").all() # Get single object user = await User.objects.get(id=42) user = await User.objects.get_or_none(email="test@test.com") ``` -------------------------------- ### Setting SQL Defaults in Oxyde Models Source: https://oxyde.fatalyst.dev/latest/guide/models Demonstrates how to set database-level default values for model fields using `db_default`. This includes examples for timestamps, UUIDs, and string literals, noting that strings require quotes. ```Python class User(Model): id: int | None = Field(default=None, db_pk=True) created_at: datetime = Field(db_default="CURRENT_TIMESTAMP") uuid: str = Field(db_default="gen_random_uuid()") # PostgreSQL status: str = Field(db_default="'active'") # Note: strings need quotes class Meta: is_table = True ``` -------------------------------- ### Initialize database connection Source: https://oxyde.fatalyst.dev/latest/faq Initializes the database connection for Oxyde using the `db.init()` method. It takes a database URL as a default connection string. ```python from oxyde import db await db.init(default="postgresql://user:pass@localhost/mydb") ``` -------------------------------- ### Best Practices Source: https://oxyde.fatalyst.dev/latest/cheatsheet Provides recommendations for efficient ORM usage. ```APIDOC ### DO ## Reuse Query for multiple operations ```python active = User.objects.filter(is_active=True) count = await active.count() users = await active.all() ``` ### Description Reusing a query object can prevent redundant database queries. ## Use bulk operations for performance ```python await User.objects.bulk_create([user1, user2, user3]) ``` ### Description Bulk operations significantly improve performance for multiple inserts, updates, or deletes. ## Use prefetch to load related objects ```python users = await User.objects.prefetch("posts").all() ``` ### Description Prefetching reduces the number of queries needed to load related objects. ``` -------------------------------- ### Python: Complex Query Conditions Source: https://oxyde.fatalyst.dev/latest/cheatsheet Illustrates how to build complex query conditions using Q objects for logical AND, OR, and NOT operations, as well as excluding specific criteria. ```python # Q expressions users = await User.objects.filter( Q(age__gte=18) & (Q(status="active") | Q(status="premium")) ).all() # Exclusion users = await User.objects.exclude(status="banned").all() ``` -------------------------------- ### Prevent get_or_create() Race Condition Source: https://oxyde.fatalyst.dev/latest/changelog Concurrent calls to `get_or_create()` attempting to create the same record could result in an `IntegrityError`. This fix implements retries on `get()` upon conflict, ensuring atomicity and preventing race conditions. ```python # get_or_create() race condition # Now retries get() on conflict to prevent IntegrityError. ``` -------------------------------- ### Handling NotFoundError in Python Source: https://oxyde.fatalyst.dev/latest/guide/exceptions Demonstrates catching `NotFoundError`, raised when a query expecting a single row (like `get()`) finds no matching records. It also shows common patterns for handling this, including using `get_or_none`. ```python try: user = await User.objects.get(id=999999) except NotFoundError as e: print(f"Not found: {e}") # "User matching query not found" ``` ```python # Option 1: Use get_or_none user = await User.objects.get_or_none(id=user_id) if user is None: return {"error": "User not found"} # Option 2: Catch exception try: user = await User.objects.get(id=user_id) except NotFoundError: raise HTTPException(404, "User not found") ``` -------------------------------- ### Best Practice: Use Context Managers for Scripts Source: https://oxyde.fatalyst.dev/latest/guide/connections Recommends using context managers for database connections within scripts to ensure automatic cleanup. ```APIDOC ## Best Practices ### 1. Use Context Managers for Scripts #### Description Ensures that database connections are automatically managed and cleaned up when using scripts. #### Method N/A (Code example) #### Endpoint N/A #### Parameters N/A #### Request Example ```python async def main(): async with db.connect("sqlite:///app.db"): # Automatic cleanup on exit await run_app() ``` #### Response N/A ``` -------------------------------- ### Multiple Databases Source: https://oxyde.fatalyst.dev/latest/cheatsheet Demonstrates how to specify databases for read and write operations. ```APIDOC ## Use replica for reading ```python users = await User.objects.filter(is_active=True).all(using="replica") ``` ### Description Specifies a database alias for read operations. ## Write to master ```python user = await User.objects.create(name="John", using="master") ``` ### Description Specifies a database alias for write operations. ``` -------------------------------- ### Performing Cross-Database Operations Source: https://oxyde.fatalyst.dev/latest/guide/connections Demonstrates how to perform operations that span across different databases. This example synchronizes user data from the main database to the analytics database by reading a user from 'default' and creating a corresponding profile in 'analytics'. ```python async def sync_user_to_analytics(user_id: int): # Read from main user = await User.objects.get(id=user_id) # Write to analytics await UserProfile.objects.create( user_id=user.id, name=user.name, using="analytics" ) ```