I have a CharField on a Django (1.9) model:
alias = models.CharField(max_length=50)
The app is being used and already has data, and there are objects using all 50 characters already. What is the simplest method to reduce the max_length of this field without getting complaints from my production database when I try to migrate? DB is postgresql if it makes a difference.
I think the right way would be simply go the development python terminal and access all the objects of that particular model and truncate the values for alias as:
for object in MyModel.objects.all():
object.alias = object.alias[:REDUCED_LENGTH]
object.save()
and, the change the max_length in the CharField in your model and run migrations.
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
),
]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With