Truncating data that violates the new max_length
condition can be done as part of the migration. In the Django-generated migration file, one would add a call to RunPython
, supplying a function that finds offending instances and corrects them, prior to applying the alteration to the column.
from django.db import migrations, models
def forwards_func(apps, schema_editor):
"""Apply a forwards migration."""
# Grab cached versions of models
TheModel = apps.get_model('the_package', 'TheModel')
db_alias = schema_editor.connection.alias
# Find all models with affected data
# Note this is overly simplistic for the example. To be more
# targeted, consider a Q() filter, to find instances whose
# field length is greater than the new maximum.
instances = TheModel.objects.using(db_alias).exclude(
the_field_being_shortened='',
)
# Truncate the data
for instance in instances:
# Note the simplicity for example, again. One may consider
# preserving a shortened value, instead.
instance.the_field_being_shortened = ''
instance.save()
def reverse_func(apps, schema_editor):
"""Undo a migration."""
# We cannot restore the data. Nothing to do here.
pass
class Migration(migrations.Migration):
dependencies = [
('the_package', 'the_last_migration'),
]
operations = [
# RunPython executes our functions
migrations.RunPython(forwards_func, reverse_func),
migrations.AlterField(
# The field alterations as generated by Django
),
]