Search code examples
pythondjangoherokudeploymentmigrate

Migrate command in django giving error when deployed to heroku


So i was trying to deploy a django app to heroku which works fine locally.

Though the deployment process completes successfully but the migrate command gives an error.

django.db.migrations.exceptions.NodeNotFoundError: Migration accounts.0001_initial dependencies reference nonexistent parent node ('auth', '0013_alter_user_email')

Here is my migration file;

import accounts.models
from django.conf import settings
import django.contrib.gis.db.models.fields
from django.db import migrations, models
import django.db.models.deletion
from django.contrib.postgres.operations import CreateExtension


class Migration(migrations.Migration):

    initial = True

    dependencies = [
        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
        ('auth', '0013_alter_user_email'),
    ]

    operations = [...]

From discussion in the comments it seems that the migration 0013_alter_user_email does not actually exist in the auth app. It is generated because I modify the user model by accessing it during runtime using User._meta.get_field('email').unique to make the email field unique.


Solution

  • You are modifying the user model at runtime causing a migration to be generated for it. This way of doing things is called monkey patching and it is a bad practice. django.contrib.auth can be said to be a 3rd party application and modifying it like this can have adverse effects one of which you are currently experiencing. What happened is that you modified the user model, and it generated a migration locally in the Django package. Since this is a package it's not part of your code and is installed separately. You cannot even run makemigrations on Heroku to solve this (not a recommended solution anyway) since any filesystem changes on Heroku are temporary and will get deleted when the dyno loads up.

    Django allows one to customize authentication [Django docs] / user model very easily. In general as a best practice in Django one should always use a custom user model when starting a project.

    The solution for you would be to delete all your migrations, drop the database, reinstall Django to make sure it is clean and unmodified and use a custom user model as described above:

    from django.contrib.auth.models import AbstractUser
    from django.utils.translation import gettext_lazy as _
    
    
    class User(AbstractUser):
        email = models.EmailField(_('email address'), blank=True, unique=True)
    

    Set this as AUTH_USER_MODEL [Django dosc] in the settings. There will be other changes needed too like registering the model for the admin site, changing some of the forms in the ModelAdmin (i.e. UserAdmin) and views and refactoring your code.