Skip to main content

Quick Start

Let's go from zero to a working database query in 5 minutes.

Step 1: Connect to a Database

import asyncio
import ryx

async def main():
# SQLite for quick testing
await ryx.setup("sqlite:///app.db")

# Or PostgreSQL for production
# await ryx.setup("postgres://user:pass@localhost/mydb")

asyncio.run(main())
tip

Use sqlite::memory: for tests — no files, no cleanup needed.

Step 2: Define a Model

from ryx import Model, CharField, IntField, BooleanField, DateTimeField

class Post(Model):
title = CharField(max_length=200)
slug = CharField(max_length=210, unique=True)
views = IntField(default=0)
active = BooleanField(default=True)
created = DateTimeField(auto_now_add=True)

class Meta:
ordering = ["-created"]

That's it. No migrations file to write — Ryx handles it.

Step 3: Run Migrations

from ryx.migrations import MigrationRunner

async def main():
await ryx.setup("sqlite:///app.db")
runner = MigrationRunner([Post])
await runner.migrate() # Creates the table

asyncio.run(main())

Or via CLI:

python -m ryx migrate --url sqlite:///app.db --models myapp.models

Step 4: Create Records

post = await Post.objects.create(
title="Hello Ryx",
slug="hello-ryx",
views=42,
)
print(f"Created post #{post.pk}")

Step 5: Query

# Simple filter
active_posts = await Post.objects.filter(active=True)

# With Q objects
popular = await Post.objects.filter(
Q(active=True) | Q(views__gte=1000)
)

# Chain it all
top_posts = await (
Post.objects
.filter(active=True)
.exclude(title__startswith="Draft")
.order_by("-views")
.limit(10)
)

# Aggregations
stats = await Post.objects.aggregate(
total_posts=Count("id"),
total_views=Sum("views"),
avg_views=Avg("views"),
)
print(stats)
# → {'total_posts': 42, 'total_views': 15000, 'avg_views': 357.14}

Step 6: Update & Delete

# Update
post.title = "Updated Title"
await post.save()

# Or bulk update
updated = await Post.objects.filter(active=False).update(active=True)

# Delete
await post.delete()

# Or bulk delete
deleted = await Post.objects.filter(views=0).delete()

Complete Example

import asyncio
import ryx
from ryx import Model, CharField, IntField, BooleanField, DateTimeField, Q, Count, Sum, Avg
from ryx.migrations import MigrationRunner

class Post(Model):
title = CharField(max_length=200)
slug = CharField(max_length=210, unique=True)
views = IntField(default=0)
active = BooleanField(default=True)
created = DateTimeField(auto_now_add=True)

class Meta:
ordering = ["-created"]

async def main():
# 1. Connect
await ryx.setup("sqlite::memory:")

# 2. Migrate
await MigrationRunner([Post]).migrate()

# 3. Create
await Post.objects.create(title="Hello Ryx", slug="hello-ryx", views=100)
await Post.objects.create(title="Rust is fast", slug="rust-fast", views=500)
await Post.objects.create(title="Draft post", slug="draft", views=0, active=False)

# 4. Query
posts = await Post.objects.filter(active=True).order_by("-views")
print(f"Found {len(posts)} active posts")

# 5. Aggregate
stats = await Post.objects.aggregate(
total=Count("id"), avg=Avg("views"), top=Max("views"),
)
print(f"Stats: {stats}")

asyncio.run(main())

Next Steps

Project Structure — Understand how Ryx is organized → Models — Deep dive into model definitions