-
-
Save leogregianin/5a1dcc6c48f54a026f10a794149e0715 to your computer and use it in GitHub Desktop.
Migrating existing columns to use django-cryptography
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # -*- coding: utf-8 -*- | |
| from __future__ import unicode_literals | |
| from django.db import migrations, models | |
| from django_cryptography.fields import encrypt | |
| app_with_model = 'account' | |
| model_with_column = 'User' | |
| column_to_encrypt = 'email_address' | |
| column_field_class = models.CharField | |
| column_attrs = {'max_length': 150} | |
| column_null_status = False | |
| temporary_column = f'temp_{column_to_encrypt}' | |
| def replicate_to_temporary(apps, schema_editor): | |
| Model = apps.get_model(app_with_model, model_with_column) | |
| for row in Model.objects.all(): | |
| setattr(row, temporary_column, getattr(row, column_to_encrypt, None)) | |
| setattr(row, column_to_encrypt, None) | |
| row.save(update_fields=[temporary_column, column_to_encrypt]) | |
| def replicate_to_real(apps, schema_editor): | |
| Model = apps.get_model(app_with_model, model_with_column) | |
| for row in Model.objects.all(): | |
| setattr(row, column_to_encrypt, getattr(row, temporary_column)) | |
| row.save(update_fields=[column_to_encrypt]) | |
| class Migration(migrations.Migration): | |
| dependencies = [ | |
| (app_with_model, '0000_whichever'), | |
| ] | |
| operations = [ | |
| # create temporary column | |
| migrations.AddField( | |
| model_name=model_with_column.lower(), | |
| name=temporary_column, | |
| field=column_field_class( | |
| verbose_name=temporary_column, null=True, **column_attrs), | |
| ), | |
| # allow null entries in the real column | |
| migrations.AlterField( | |
| model_name=model_with_column.lower(), | |
| name=column_to_encrypt, | |
| field=column_field_class( | |
| verbose_name=column_to_encrypt, null=True, **column_attrs), | |
| ), | |
| # push all data from real to temporary | |
| migrations.RunPython(replicate_to_temporary), | |
| # encrypt the real column (still allowing null values) | |
| migrations.AlterField( | |
| model_name=model_with_column.lower(), | |
| name=column_to_encrypt, | |
| field=encrypt(column_field_class( | |
| verbose_name=column_to_encrypt, null=True, **column_attrs)), | |
| ), | |
| # push all data from temporary to real (encrypting in the processes) | |
| migrations.RunPython(replicate_to_real), | |
| # remove the temporary column | |
| migrations.RemoveField( | |
| model_name=model_with_column.lower(), | |
| name=temporary_column), | |
| # disallow null values (if applicable) | |
| migrations.AlterField( | |
| model_name=model_with_column.lower(), | |
| name=column_to_encrypt, | |
| field=encrypt(column_field_class( | |
| verbose_name=column_to_encrypt, null=column_null_status, | |
| **column_attrs)), | |
| ), | |
| ] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment