I'm using django1.7, python 2.7 and mysql. I'm writing some tests to test that my data migrations work properly and in the process require that my data migrations be reversible.
class Migration(migrations.Migration):
dependencies = [
('myapp', '0001_initial'),
]
operations = [
migrations.RunSQL("SET FOREIGN_KEY_CHECKS=0;", reverse_sql="SET FOREIGN_KEY_CHECKS=1;"),
migrations.RunPython(load_fixture, reverse_code=unload_fixture),
migrations.RunSQL("SET FOREIGN_KEY_CHECKS=1;", reverse_sql='')
]
def unload_fixture(apps, schema_editor):
with open(myfile, 'rb') as fixture:
objects = serializers.deserialize('json', fixture, ignorenonexistent=True)
for obj in objects:
obj_name = type(obj.object).__name__
Model = apps.get_model('myapp', obj_name)
database_object = Model.objects.get(pk=obj.object.pk)
if obj.object == database_object: #equality overridden, checks all fields
database_object.delete()
class RuleFile(MyAppModel):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=128)
creator = models.ForeignKey(User, db_column='creator')
firmware = models.ForeignKey(Firmware)
I've needed to set FOREIGN_KEY_CHECKS=0 so that I can insert my data migration otherwise it complains of missing references to foreign keys when going forward. Now when I reverse and delete objects, it will throw a DoesNotExist error even though I can see the object in mention in the database and it is because of foreign keys b/c I can still locate the object in python if I do not delete any of the foreign key objects, indicating that the deleting of objects affects the deleting of other objects down the line. My question is how does one write reversible, idempotent data migrations using Django correctly with foreign keys? My theory is:
Forwards --> Add the object if it doesn't already exist in the database
Reverse --> Remove the object only if it matches what you have in fixture so that you can add it back
POSSIBLE METHOD - use transactions so entries are not deleted right away
Aucun commentaire:
Enregistrer un commentaire