Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/diegolozadev/DataMed/llms.txt

Use this file to discover all available pages before exploring further.

Database Migrations

Django migrations are version control for your database schema. DataMed uses migrations to track all schema changes, making it easy to evolve the database structure over time.

Understanding Migrations

Migrations are Python files that describe changes to database schema:
  • Create tables: New models
  • Add fields: New columns
  • Modify fields: Change types, add constraints
  • Delete fields: Remove columns
  • Rename fields: Change column names
  • Data migrations: Transform existing data

Migration Files

Migrations are stored in apps/<app>/migrations/ directories:
apps/patients/migrations/
├── 0001_initial.py                    # Initial Patient model
├── 0002_alter_patient_fecha_ingreso.py  # Modified field
├── 0003_ingreso.py                      # Added Ingreso model
├── 0004_remove_patient_barrio_...py     # Removed fields
├── 0005_remove_ingreso_created_at_...py # Multiple changes
└── __init__.py

Anatomy of a Migration File

apps/patients/migrations/0003_ingreso.py
from django.db import migrations, models
import django.db.models.deletion

class Migration(migrations.Migration):
    dependencies = [
        ('patients', '0002_alter_patient_fecha_ingreso'),
    ]

    operations = [
        migrations.CreateModel(
            name='Ingreso',
            fields=[
                ('id', models.BigAutoField(auto_created=True, primary_key=True)),
                ('fecha_inicio', models.DateField()),
                ('fecha_fin', models.DateField(blank=True, null=True)),
                ('estado', models.CharField(default='ACTIVO', max_length=20)),
                ('motivo', models.TextField(blank=True, null=True)),
                ('paciente', models.ForeignKey(
                    on_delete=django.db.models.deletion.CASCADE,
                    related_name='ingresos',
                    to='patients.patient'
                )),
            ],
        ),
    ]
Key Components:
  • dependencies: Previous migration that must run first
  • operations: List of schema changes to apply
  • CreateModel, AddField, AlterField: Operation types

Creating Migrations

After modifying models, generate migrations automatically:
python manage.py makemigrations
Output:
Migrations for 'patients':
  apps/patients/migrations/0011_alter_patient_ciudad.py
    - Alter field ciudad on patient

Creating Named Migrations

python manage.py makemigrations --name add_capita_calculation

Dry Run (Preview)

python manage.py makemigrations --dry-run

Applying Migrations

Apply pending migrations to the database:
python manage.py migrate
Output:
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, dashboard, exams, patients, sessions, users
Running migrations:
  Applying patients.0011_alter_patient_ciudad... OK
  Applying exams.0030_seguimientoadaptacion... OK

Apply Specific App Migrations

python manage.py migrate patients

Apply Up To Specific Migration

python manage.py migrate patients 0010

Viewing Migration Status

Check which migrations are applied:
python manage.py showmigrations
Output:
patients
 [X] 0001_initial
 [X] 0002_alter_patient_fecha_ingreso
 [X] 0003_ingreso
 [X] 0004_remove_patient_barrio_remove_patient_direccion_and_more
 [X] 0005_remove_ingreso_created_at_alter_ingreso_estado_and_more
 [ ] 0011_alter_patient_ciudad
Legend:
  • [X]: Applied
  • [ ]: Pending

Show Migrations for Specific App

python manage.py showmigrations patients

Rollback Migrations

Revert to a previous migration:
# Rollback to migration 0010
python manage.py migrate patients 0010
Rolling back migrations may cause data loss. Always backup your database first.

Rollback All Migrations in App

python manage.py migrate patients zero

Common Migration Operations

Adding a New Field

1

Modify Model

Add field to model:
apps/patients/models.py
class Patient(models.Model):
    # ... existing fields ...
    notas_adicionales = models.TextField(blank=True, null=True)
2

Generate Migration

python manage.py makemigrations
3

Review Migration

Check generated file in apps/patients/migrations/
4

Apply Migration

python manage.py migrate

Renaming a Field

1

Modify Model

Rename field:
# Before: usu_diario
# After:  uso_diario
uso_diario = models.DecimalField(max_digits=5, decimal_places=2)
2

Generate Migration

python manage.py makemigrations
Django will ask:
Did you rename monitoreo.usu_diario to monitoreo.uso_diario? [y/N]
Answer y to generate a RenameField operation instead of RemoveField + AddField.
3

Apply Migration

python manage.py migrate
Renaming preserves existing data. If Django doesn’t detect the rename, you’ll lose data!

Adding a Model

See the Ingreso model addition in migration 0003_ingreso.py:
operations = [
    migrations.CreateModel(
        name='Ingreso',
        fields=[
            ('id', models.BigAutoField(auto_created=True, primary_key=True)),
            ('paciente', models.ForeignKey(...)),
            ('fecha_inicio', models.DateField()),
            # ... other fields ...
        ],
    ),
]

Removing a Model

operations = [
    migrations.DeleteModel(name='OldModel'),
]
Irreversible: Dropping a model deletes the table and all data permanently.

Data Migrations

Migrate existing data when schema changes require it.

Example: Moving mes_capita from Patient to Ingreso

from django.db import migrations

def migrate_mes_capita(apps, schema_editor):
    Patient = apps.get_model('patients', 'Patient')
    Ingreso = apps.get_model('patients', 'Ingreso')
    
    for patient in Patient.objects.all():
        ingreso = patient.ingresos.first()
        if ingreso:
            # mes_capita is now a computed property, no data to migrate
            pass

class Migration(migrations.Migration):
    dependencies = [
        ('patients', '0005_remove_ingreso_created_at_alter_ingreso_estado_and_more'),
    ]
    
    operations = [
        migrations.RunPython(migrate_mes_capita),
    ]

Empty Migration for Data Operations

python manage.py makemigrations --empty patients --name populate_defaults

Migration History in DataMed

Key migrations in DataMed’s evolution:

Patients App

  • 0001_initial: Created Patient model with all demographics
  • 0003_ingreso: Added Ingreso model for program cycles
  • 0006_remove_patient_mes_capita: Moved capita tracking to Ingreso
  • 0007_alter_ingreso_options_alter_ingreso_estado: Refined Ingreso states

Exams App

  • 0001_initial: Created Monitoreo and Nutricion models
  • 0004_psicologia: Added psychology assessment model
  • 0007_polisomnografiatitulacion_polisomnografiabasal: Sleep study models
  • 0010_equipomedico: Medical equipment tracking
  • 0016_remove_equipomedico_patient_…: Migrated exams from Patient to Ingreso
  • 0030_seguimientoadaptacion: Adaptation follow-up notes

Troubleshooting

Error: You have X unapplied migration(s)...Solution:
python manage.py migrate
python manage.py makemigrations
Error: Conflicting migrations detectedSolution:
# Merge migrations
python manage.py makemigrations --merge
Error: django.db.utils.IntegrityErrorSolution:
  • Check for data that violates new constraints
  • Write a data migration to fix existing data first
  • Roll back migration: python manage.py migrate app_name previous_migration
When you manually applied changes or need to mark a migration as applied:
python manage.py migrate --fake patients 0011
Use sparingly - can cause inconsistencies.
Build script shows migration errors:Solution:
# Check migration status
python manage.py showmigrations

# Try migrating again
python manage.py migrate --noinput

# If specific migration fails, investigate:
python manage.py migrate patients 0010  # Apply up to 0010
python manage.py sqlmigrate patients 0011  # View SQL for problematic migration

Best Practices

Always generate migrations in development - Don’t create migrations directly in production.
Review generated migrations - Check SQL with python manage.py sqlmigrate app_name migration_number before applying.
Commit migrations to git - Migrations are code and should be version controlled.
Test migrations on copy of production data - Catch issues before they hit production.
Backup before major migrations - Always backup production database before schema changes.
Never edit applied migrations - Create a new migration to fix issues. Editing applied migrations causes inconsistencies.

Production Deployment

Migrations are automatically applied during deployment:

Render (build.sh)

build.sh
python manage.py migrate --noinput

Procfile

web: python manage.py migrate --noinput && gunicorn config.wsgi

Docker

CMD python manage.py migrate --noinput && gunicorn config.wsgi

Inspecting SQL

View the actual SQL that will be executed:
python manage.py sqlmigrate patients 0011
Output:
BEGIN;
ALTER TABLE "patients_patient" ALTER COLUMN "ciudad" TYPE varchar(100);
COMMIT;

Next Steps

Database Schema

Understand DataMed’s data model

Backup & Restore

Protect data before migrations

Deployment

See how migrations run in production

Configuration

Configure database settings