This document provides a quick reference for seeding the inventory database with tenant-scoped data.
python manage.py seed_database --clear --create-default
This will:
python manage.py seed_database --clear --tenant=acme-corp
This will seed data for the “acme-corp” tenant. The tenant must already exist.
# Create Default tenant and seed all data
python manage.py seed_database --clear --create-default
# Create tenants
python manage.py createtenant --name="Tenant A" --slug="tenant-a"
python manage.py createtenant --name="Tenant B" --slug="tenant-b"
# Seed data for each tenant independently
python manage.py seed_database --clear --tenant=tenant-a
python manage.py seed_database --clear --tenant=tenant-b
# Verify isolation
python manage.py shell
>>> from inventory.models import Product
>>> from tenants.models import Tenant
>>> Tenant.objects.get(slug="tenant-a").inventory_product_set.count()
15
>>> Tenant.objects.get(slug="tenant-b").inventory_product_set.count()
15
# Seed only categories and products for a tenant
python manage.py seed_database --models categories,products --tenant=acme-corp
# Available models: categories, products, locations, records, movements
# Seed without clearing existing data (soft seed)
python manage.py seed_database --tenant=acme-corp
# Run seeding silently
python manage.py seed_database --clear --create-default --quiet
Use SeederManager directly in scripts or tests:
from inventory.seeders import SeederManager
from tenants.models import Tenant
from tenants.context import set_current_tenant, clear_current_tenant
# Get or create a tenant
tenant, created = Tenant.objects.get_or_create(
slug="acme-corp",
defaults={"name": "ACME Corp", "is_active": True}
)
# Set tenant context (required for audit logging)
set_current_tenant(tenant)
try:
# Seed everything for this tenant
manager = SeederManager(verbose=True, clear_data=True)
manager.seed(tenant=tenant)
finally:
# Always clear context after seeding
clear_current_tenant()
Solution 1: Auto-create Default tenant
python manage.py seed_database --clear --create-default
Solution 2: Use an existing tenant
# List available tenants
python manage.py shell
>>> from tenants.models import Tenant
>>> list(Tenant.objects.values_list('slug', flat=True))
# Seed for an existing tenant
python manage.py seed_database --clear --tenant=existing-slug
Solution:
# Create the tenant first
python manage.py createtenant --name="XYZ Corp" --slug="xyz"
# Then seed for it
python manage.py seed_database --clear --tenant=xyz
Problem: Existing data without tenant assignment (from old seeding runs before migration TS-06)
Solution: Run the migration to backfill:
python manage.py migrate
This migration:
tenant field non-nullable to prevent future orphaningVerify no orphaned data:
python manage.py shell
>>> from inventory.models import Product
>>> Product.objects.filter(tenant__isnull=True).count()
0 # Should be zero
Problem: Data was seeded to the wrong tenant by mistake
Solution: Clear and reseed for the correct tenant:
python manage.py seed_database --clear --tenant=correct-tenant-slug
During seeding, the tenant context is automatically set via set_current_tenant(tenant). This ensures:
created_by) respect tenant contextTenantAwareManagertenant assignedAll seeders are wrapped in transactions:
| Seeder | Purpose | Tenant-Aware |
|---|---|---|
TenantSeeder |
Creates or retrieves the “Default” tenant | Yes |
CategorySeeder |
Creates product categories (hierarchical) | Yes |
ProductSeeder |
Creates products across categories | Yes |
StockLocationSeeder |
Creates warehouse structure (hierarchical) | Yes |
StockRecordSeeder |
Creates stock-location associations | Yes |
StockMovementSeeder |
Creates movement history | Yes |
LowStockSeeder |
Creates low-stock scenarios for alerts | Yes |
# Fresh start with complete dataset (uses Default tenant)
python manage.py seed_database --clear --create-default
# Add products to existing categories (same tenant)
python manage.py seed_database --models products --tenant=acme-corp
# Seed for a different tenant
python manage.py seed_database --clear --tenant=other-tenant
from inventory.seeders import SeederManager
from tenants.models import Tenant
class MyTestCase(TestCase):
@classmethod
def setUpClass(cls):
super().setUpClass()
# Create test tenant
tenant = Tenant.objects.create(
name="Test Tenant",
slug="test-tenant",
is_active=True
)
# Seed data into it
SeederManager(verbose=False, clear_data=True).seed(tenant=tenant)
cls.tenant = tenant
def test_product_count(self):
from inventory.models import Product
count = Product.objects.filter(tenant=self.tenant).count()
self.assertEqual(count, 15)
# Create tenants first
python manage.py createtenant --name="Tenant A" --slug="tenant-a"
python manage.py createtenant --name="Tenant B" --slug="tenant-b"
# Seed data for each
python manage.py seed_database --clear --tenant=tenant-a
python manage.py seed_database --clear --tenant=tenant-b
# Verify isolation: data is segregated by tenant
python manage.py shell
>>> from inventory.models import Product
>>> from tenants.models import Tenant
>>> tenant_a = Tenant.objects.get(slug="tenant-a")
>>> Product.objects.filter(tenant=tenant_a).count()
15 # 15 products for tenant-a
>>> tenant_b = Tenant.objects.get(slug="tenant-b")
>>> Product.objects.filter(tenant=tenant_b).count()
15 # 15 products for tenant-b (isolated)
python manage.py seed_database --helppython manage.py shell → Tenant.objects.all()