Skip to main content
Inventario uses Django’s ORM with support for PostgreSQL in production and SQLite for development. Database configuration is managed through environment variables.

Database Configuration

PostgreSQL with dj-database-url

The database is configured using dj-database-url for easy environment-based setup:
Configuration:
  • Environment variable: DATABASE_URL
  • Connection pooling: conn_max_age=600 (10 minutes)
  • Fallback: SQLite at db.sqlite3 if DATABASE_URL not set

Database URL Format

PostgreSQL connection string format:
Example:
Components:
  • postgresql:// - Database engine
  • username:password - Credentials
  • host:port - Database server location
  • database_name - Database name

SQLite Fallback (Development)

When DATABASE_URL is not set, Inventario uses SQLite:
Location: db.sqlite3 in project root
SQLite is suitable for development only. Always use PostgreSQL for production:
  • SQLite lacks concurrent write support
  • No user management or access control
  • Limited performance under load
  • File-based storage not suitable for containerized deployments

Database Setup

Development Setup

For local development with SQLite:
SQLite database is created automatically on first migration.

Production Setup (PostgreSQL)

  1. Provision PostgreSQL database On Railway:
    On Render:
    Manual setup:
  2. Set environment variable
  3. Run migrations

Migrations

Django migrations track database schema changes.

Running Migrations

Apply pending migrations:
The build.sh script automatically runs migrations on deployment:

Creating Migrations

After changing models, create migrations:
This generates migration files in each app’s migrations/ directory.
Always commit migration files to version control. They ensure database schema stays in sync across environments.

Checking Migration Status

View applied and pending migrations:
View SQL for a migration:

Rolling Back Migrations

Rollback to a specific migration:
Rollback all migrations for an app:
Rolling back migrations in production can cause data loss. Always backup the database first.

Database Applications

Inventario includes these database-backed applications:
  • applications.usuarios - User management
  • applications.cuentas - Account management with custom user model
  • applications.proveedores - Supplier records
  • applications.productos - Product inventory
  • applications.clientes - Customer records
  • applications.ventas - Sales transactions
  • applications.reportes - Report data
  • applications.compras - Purchase orders
  • applications.configuracion - System configuration
  • applications.devoluciones - Return/refund records
Each application has its own migration directory and models.

Custom User Model

Inventario uses a custom user model:
This model is defined in applications.cuentas.models and extends Django’s authentication.
Changing AUTH_USER_MODEL after initial migrations is extremely difficult. This must be set before first migration.

Connection Pooling

Keeps database connections open for 10 minutes:
  • Reduces connection overhead
  • Improves response times
  • Prevents connection exhaustion
Adjust based on:
  • Database connection limits
  • Application server count
  • Expected concurrent users
Formula: max_connections / (workers * servers) ≈ 600 seconds

Database Backups

PostgreSQL Backups

Create a backup:
With DATABASE_URL:

Restore from Backup

Restore with -c (clean) drops existing objects. Test on a separate database first.

Automated Backups

On Railway:
  • Configure automatic backups in Railway dashboard
  • Backups are taken daily by default
On Render:
  • Enable automatic backups in database settings
  • Choose retention period
Manual automation:
Run daily with cron:

Database Management

Django Database Shell

Open PostgreSQL shell through Django:
This uses the configured DATABASE_URL automatically.

Inspecting the Database

View all tables:
Describe a table:
Query data:

Django Shell

Interact with models in Python:

Database Optimization

Indexing

Django automatically creates indexes for:
  • Primary keys
  • Foreign keys
  • Fields with unique=True
  • Fields with db_index=True
Add custom indexes in models:

Query Optimization

Use select_related() for foreign keys:
Use prefetch_related() for many-to-many:

Database Monitoring

Monitor these metrics:
  • Connection count
  • Query execution time
  • Slow queries
  • Database size
  • Index usage
Enable query logging in development:

Troubleshooting

”No such table” Error

Migrations haven’t been applied:

Connection Refused

Check DATABASE_URL is correct:
Test PostgreSQL connection:

Authentication Failed

Verify credentials in DATABASE_URL:
  • Username and password are correct
  • User has access to the database
  • Database exists

Too Many Connections

Reduce conn_max_age or increase PostgreSQL max_connections:

Migration Conflicts

If multiple developers create migrations simultaneously:

Database Locked (SQLite)

SQLite locks the entire database for writes. Switch to PostgreSQL for production:

Data Import/Export

Export Data (JSON)

Export specific app:

Import Data

loaddata can create duplicate data. Use with caution in production.

Migration from SQLite to PostgreSQL

To migrate from development SQLite to production PostgreSQL:
  1. Export data from SQLite
  2. Configure PostgreSQL
  3. Run migrations
  4. Import data
  5. Verify data