Managers¶
Managers provide the primary interface for database-table operations in django-api-orm. Every model has a objects manager that provides methods for creating, retrieving, and managing instances.
Accessing Managers¶
The default manager is available as objects on your model:
# Access the manager
User.objects
# Manager is only available after model registration
from django_api_orm import ServiceClient, register_models
with ServiceClient(base_url="https://api.example.com") as client:
register_models(client, User)
# Now User.objects is available
Manager Methods¶
QuerySet Methods¶
All QuerySet methods are available on the manager:
# These are equivalent
User.objects.filter(active=True)
User.objects.all().filter(active=True)
# Manager methods return QuerySets
queryset = User.objects.filter(active=True)
admin_queryset = queryset.filter(role="admin")
See QuerySets for complete QuerySet documentation.
Creation Methods¶
create()¶
Create and save a new instance:
user = User.objects.create(
name="Alice Smith",
email="alice@example.com",
active=True
)
# Equivalent to:
user = User(name="Alice Smith", email="alice@example.com", active=True, _client=client)
user.save()
This method:
Validates the data using Pydantic
Makes a POST request to the API
Returns the created instance with API-assigned fields (like
id)
bulk_create()¶
Create multiple instances at once:
users = User.objects.bulk_create([
{"name": "Alice", "email": "alice@example.com"},
{"name": "Bob", "email": "bob@example.com"},
{"name": "Charlie", "email": "charlie@example.com"}
])
# Returns a list of created instances
for user in users:
print(f"Created user {user.id}: {user.name}")
Note: This makes individual POST requests for each instance (no bulk endpoint is assumed).
get_or_create()¶
Get an existing instance or create a new one:
user, created = User.objects.get_or_create(
email="alice@example.com",
defaults={"name": "Alice Smith", "role": "user"}
)
if created:
print(f"Created new user: {user.name}")
else:
print(f"Found existing user: {user.name}")
The first argument(s) are used for the lookup, and defaults provides additional fields for creation.
update_or_create()¶
Update an existing instance or create a new one:
user, created = User.objects.update_or_create(
email="alice@example.com",
defaults={"name": "Alice Updated", "role": "admin"}
)
if created:
print(f"Created new user: {user.name}")
else:
print(f"Updated existing user: {user.name}")
This method:
Tries to get an instance matching the lookup fields
If found, updates it with the
defaultsfieldsIf not found, creates a new instance with all fields
Retrieval Methods¶
all()¶
Get all instances:
all_users = User.objects.all()
Returns a QuerySet that can be further filtered:
active_users = User.objects.all().filter(active=True)
filter()¶
Filter instances by field values:
active_users = User.objects.filter(active=True)
admins = User.objects.filter(role="admin")
# Multiple filters (AND logic)
active_admins = User.objects.filter(active=True, role="admin")
exclude()¶
Exclude instances by field values:
non_admins = User.objects.exclude(role="admin")
active_non_guests = User.objects.filter(active=True).exclude(role="guest")
get()¶
Get a single instance:
from django_api_orm.exceptions import DoesNotExist, MultipleObjectsReturned
try:
user = User.objects.get(id=1)
except DoesNotExist:
print("User not found")
except MultipleObjectsReturned:
print("Multiple users found")
first()¶
Get the first instance or None:
first_user = User.objects.first()
if first_user:
print(f"First user: {first_user.name}")
# With ordering
newest_user = User.objects.order_by("-created_at").first()
last()¶
Get the last instance or None:
last_user = User.objects.last()
if last_user:
print(f"Last user: {last_user.name}")
# With ordering
oldest_user = User.objects.order_by("created_at").last()
Utility Methods¶
count()¶
Get the count of instances:
total_users = User.objects.count()
active_users = User.objects.filter(active=True).count()
print(f"{active_users} out of {total_users} users are active")
exists()¶
Check if any instances exist:
has_users = User.objects.exists()
has_admins = User.objects.filter(role="admin").exists()
if not has_admins:
print("No admin users found!")
Ordering Methods¶
order_by()¶
Order instances by one or more fields:
# Ascending order
users = User.objects.order_by("name")
# Descending order
users = User.objects.order_by("-created_at")
# Multiple fields
users = User.objects.order_by("role", "-name")
Async Managers¶
Async managers work the same way but require await for operations that return instances or data:
from django_api_orm import AsyncAPIModel, AsyncServiceClient, register_async_models
class User(AsyncAPIModel):
_schema_class = UserSchema
_endpoint = "/api/v1/users/"
async with AsyncServiceClient(base_url="https://api.example.com") as client:
register_async_models(client, User)
# Await creation
user = await User.objects.create(name="Alice", email="alice@example.com")
# Await retrieval
user = await User.objects.get(id=1)
first_user = await User.objects.first()
# Await get_or_create
user, created = await User.objects.get_or_create(
email="alice@example.com",
defaults={"name": "Alice"}
)
# QuerySet methods don't need await until evaluation
queryset = User.objects.filter(active=True) # No await
async for user in queryset: # Await during iteration
print(user.name)
# Await count/exists
count = await User.objects.count()
exists = await User.objects.exists()
See Async Support for complete async documentation.
Custom Managers¶
You can create custom managers to encapsulate common queries:
from django_api_orm import Manager, APIModel
class UserManager(Manager):
"""Custom manager for User model."""
def active(self):
"""Get only active users."""
return self.filter(active=True)
def admins(self):
"""Get only admin users."""
return self.filter(role="admin")
def active_admins(self):
"""Get active admin users."""
return self.active().admins()
class User(APIModel):
_schema_class = UserSchema
_endpoint = "/api/v1/users/"
# Override the default manager
objects = UserManager()
# Usage
active_users = User.objects.active()
admins = User.objects.admins()
active_admins = User.objects.active_admins()
Best Practices¶
Use create() over manual instantiation: More concise and handles client injection
Use get_or_create() for idempotency: Prevents duplicate creation
Use exists() instead of count() > 0: More efficient for existence checks
Chain filters for readability:
User.objects.filter(active=True).filter(role="admin")Use custom managers for common queries: Encapsulate business logic
Remember async/await: Don’t forget to await async manager methods
Common Patterns¶
Pagination¶
page_size = 20
page = 1
# Get page 1 (offset 0, limit 20)
users = User.objects.all()[(page - 1) * page_size:page * page_size]
Conditional Creation¶
# Only create if doesn't exist
if not User.objects.filter(email="alice@example.com").exists():
User.objects.create(name="Alice", email="alice@example.com")
# Or use get_or_create
user, created = User.objects.get_or_create(
email="alice@example.com",
defaults={"name": "Alice"}
)
Batch Processing¶
# Create multiple users
users_data = [
{"name": "Alice", "email": "alice@example.com"},
{"name": "Bob", "email": "bob@example.com"},
{"name": "Charlie", "email": "charlie@example.com"}
]
users = User.objects.bulk_create(users_data)
# Process in batches
batch_size = 100
offset = 0
while True:
batch = User.objects.all()[offset:offset + batch_size]
if not batch:
break
for user in batch:
# Process user
pass
offset += batch_size
Finding or Creating Defaults¶
# Find admin or create a default one
admin, created = User.objects.get_or_create(
role="admin",
defaults={
"name": "Default Admin",
"email": "admin@example.com",
"active": True
}
)
Examples¶
# Create a user
user = User.objects.create(
name="Alice Smith",
email="alice@example.com",
role="admin"
)
# Get or create pattern
user, created = User.objects.get_or_create(
email="bob@example.com",
defaults={"name": "Bob Jones", "role": "user"}
)
# Update or create pattern
user, created = User.objects.update_or_create(
email="charlie@example.com",
defaults={"name": "Charlie Brown", "role": "user", "active": True}
)
# Bulk creation
users = User.objects.bulk_create([
{"name": f"User {i}", "email": f"user{i}@example.com"}
for i in range(10)
])
# Common queries via manager
active_count = User.objects.filter(active=True).count()
has_admins = User.objects.filter(role="admin").exists()
newest_user = User.objects.order_by("-created_at").first()
Next Steps¶
Learn about QuerySets for advanced querying
See Models for working with instances
Explore Async Support for async manager usage