2

I have quite a complex project architecture which involves several applications whose models contains cross references.

For example, I have a billing.Premium model - which belongs to the billing app - that is referenced by another model whose name is payments.PaymentJob through a one to one field:

('premium', models.OneToOneField(on_delete=django.db.models.deletion.PROTECT, to='billing.Premium', verbose_name='premium'))

(This code comes from one of payment's migrations)

But I have come to some point when I need to rename billing.Premium to billing.PremiumInstallment and this is when the funny part comes: after having refactored my code to replace the model name, I try to django-admin makemigrations, it leads to the following error:

ValueError: The field payments.PaymentJob.premium was declared with a lazy reference to 'billing.premium', but app 'billing' doesn't provide model 'premium'.

It appears like my migration has been broken since I have renamed the model of an external application. I do not know how to fix this in a fancy way, I mean generating some migration without error and that would be applied when I run django-admin migrate.

Any idea?

Geoffrey R.
  • 1,907
  • 1
  • 19
  • 32
  • I am not so experienced with Django modelling, but from the error is clear that has you have renamed the model referenced by another one, then changed are not migrated as the reference isn't found anymore. Have a look at this as from your error could be solved making correct steps on not simple architecture https://stackoverflow.com/questions/25091130/django-migration-strategy-for-renaming-a-model-and-relationship-fields – Carmine Tambascia Oct 23 '17 at 12:43
  • I did, but all the models are within the same app wheareas I have two models in two separated apps, and I cannot manage to refactor properly through the described method... – Geoffrey R. Oct 23 '17 at 12:52

1 Answers1

0

According to the docs for the RenameModel operation

You may have to manually add this if you change the model’s name and quite a few of its fields at once; to the autodetector, this will look like you deleted a model with the old name and added a new one with a different name, and the migration it creates will lose any data in the old table.

You should manually create a migration and add the RenameModel operation to it

class Migration(migrations.Migration):

    dependencies = [
        ('billing', 'xxxx_previous_migration'), 
    ]

    operations = [
        migrations.RenameModel('Premium', 'PremiumInstallment')
    ]
Iain Shelvington
  • 31,030
  • 3
  • 31
  • 50
  • Do I have to edit the other migration to point to `billing.PremiumInstallment` rather than `billing.Premium` then? Because now the migration is kind of buggy since it points to a model which does not exist anymore. – Geoffrey R. Oct 23 '17 at 12:43
  • I believe better you check all model that depend on the one you renamed – Carmine Tambascia Oct 23 '17 at 13:10
  • An interesting point -- to make sure that your manual migration accounts for ALL of your model-changes, after creating and saving your custom migration file, run `python manage.py makemigrations`. That will make a migration with all the changes that your custom migration did not account for. Good for bookkeeping and double-checking. – Sam Bobel Oct 23 '17 at 14:20