0

I have been working on a project for a while, and I have been having no trouble with migrations. I decided reset the database and migrations, which I do from time to time. I went to delete all migrations, make them again, and after recreating the database, apply the migrations, at which point, I get the error "Migration users.0001_initial is applied before its dependency auth.0012_alter_user_first_name_max_length on database 'default'."

Now, auth.0012_alter_user_first_name_max_length is apparently coming from django.contrib.auth, which is part of core django, so I don't see why I need any dependency on its migrations for a new project, yet whenever I make migrations on this project from the beginning, it adds a dependency to my user model of auth.0012_alter_user_first_name_max_length. I don't know why it does that, when it apparently wasn't doing that yesterday, but I am now having to remove that dependency from the user migration manually before it will migrate.

What might cause this.

Here is my users.models.py file. Maybe someone can figure out what would be so odd about it that it would do this.

from django.contrib.auth.models import AbstractUser
from django.db.models import CharField, EmailField
from django.urls import reverse
from django.utils.translation import gettext_lazy as _
from phonenumber_field.modelfields import PhoneNumberField
from django.contrib.auth.models import UserManager
from django.db.models import Q


# Override UserManager and allow login with both username and email address
class CustomUserManager(UserManager):
    def get_by_natural_key(self, username):
        return self.get(
            Q(**{self.model.USERNAME_FIELD: username}) |
            Q(**{self.model.EMAIL_FIELD: username})
        )


class User(AbstractUser):
    class Meta(object):
        unique_together = ('email',)
    email = EmailField(_('email address'), unique=True, blank=True, max_length=255)
    phone_number = PhoneNumberField(_('Phone number'), blank=True)
    address = CharField(_("Street address"), blank=True, max_length=255)
    city = CharField(_("City"), blank=True, max_length=255)
    state = CharField(_("State"), blank=True, max_length=255)
    zip = CharField(_("ZIP"), blank=True, max_length=255)

    USERNAME_FIELD = 'username'
    REQUIRED_FIELDS = ['first_name', 'last_name', 'email']
    # for allowing both username and email login
    objects = CustomUserManager()

    def get_absolute_url(self):
        """Get url for user's detail view.

        Returns:
            str: URL for user detail.

        """
        return reverse("users:detail", kwargs={"username": self.username})

PoDuck
  • 1,381
  • 15
  • 38
  • How did you re-create the database? – Adithya Jan 02 '21 at 15:09
  • sudo -u postgres psql -> drop database mydatabase; create database mydatabase; grant all privileges on database mydatabase to myuser; This should have no previous information at all. – PoDuck Jan 02 '21 at 15:27

3 Answers3

1

This worked for me

  1. Delete the database db.sqlite3.
  2. Delete the app/migrations folder.

settings.py:

INSTALLED_APPS = [
...
#'django.contrib.admin',
...
]

urls.py:

urlpatterns = [
    path('profile/', include('restapp.urls')),
    #path('admin/', admin.site.urls),
]

migrate your table:

python manage.py makemigrations      
python manage.py migrate

Uncomment both urls and this:

INSTALLED_APPS = [
...
'django.contrib.admin',
...
]

Again :

python manage.py makemigrations      
python manage.py migrate

For more detail visit..

Pradip Kachhadiya
  • 2,067
  • 10
  • 28
  • 1
    That does seem to make things work, but I don't see why it should be necessary, or what causes this problem. This model isn't new. It was the first model I created. I've been working on other parts of the project for a week now. I just noticed it because I decided to clear out the database. – PoDuck Jan 04 '21 at 14:12
1

Why is the error happening?

Django keeps track of what migrations have been run in a table called django_migrations. When you run migrate it:

  1. checks which migrations have been run, and which need to be run
  2. then records which migrations it runs as it runs them.

The InconsistentMigrationHistory error is raised when django detects that a migration has somehow been run, when it should be impossible (e.g. if it has been run but one of it's dependencies hasn't run).

I don't know how you have deleted your database, but clearly this table (django_migrations) hasn't been deleted properly, or it's been meddled with since being wiped. This error couldn't have been raised otherwise. It is very odd that users.0001_initial has been applied, and yet auth.0012_alter_user_first_name_max_length hasn't. I'm really not sure how this could have happened. Have you done any manual editing of that table???

How to fix it?

Half deleting your database as described above is going to cause you much bigger problems than just the error above. If some migrations aren't running because django thinks they're already applied when they're not, then your code and your db will potentially be totally out of sync. Make sure you've completely wiped your database properly (in particular the django_migrations table).

Can I just delete the problematic dependency?

No, this will probably cause you problems. Since User inherits from AbstractUser, it will inherit user_permissions which is a many-to-many field with auth.Permission. (It will also inherit a many-to-many field with auth.Group).

For your new migration to work correctly, it needs to first wait until auth.Permission (and auth.Group) is set up properly, so it can set up the many-to-many field correctly. This need for the contrib.auth migrations to run first before your new migration runs is the reason for the dependency on auth_0012....

(The reason it's the last migration in contrib.auth, and not the last one involving Permission or Group is just the way the makemigrations algorithm works. It's not quite clever enough to figure out which migration to point at, so it just points to the last one in that app.)

tim-mccurrach
  • 6,395
  • 4
  • 23
  • 41
  • I have been using django for almost 10 years now, and have never seen this problem. If I have issues with migrations and start with an empty database and delete migrations, Django has never had a problem creating the database. I do see your point about the dependency though. – PoDuck Jan 04 '21 at 14:09
  • Yeah, it's definitely a weird one. But that `django_migrations` table must be non-empty for that error to be raised. Maybe something went wrong half way through deleting the database??? – tim-mccurrach Jan 04 '21 at 14:16
  • Is it still causing a problem? – tim-mccurrach Jan 04 '21 at 14:17
  • I tried Pradip's solution this morning, and it seemed to work fine, but I just tried it again twice, foregoing his solution, and it all went smoothly without having to remove `django.contrib.admin`. Also, the dependency is in the initial migration. I'm not sure what's going on. I did this several times on Saturday, with no luck, but today it seems to be working fine. – PoDuck Jan 04 '21 at 19:05
  • Most likely a random error reseting the database then. The dependency in `admin` is a separate issue. – tim-mccurrach Jan 04 '21 at 20:20
  • "It is very odd that users.0001_initial has been applied, and yet auth.0012_alter_user_first_name_max_length hasn't. I'm really not sure how this could have happened." - This can easily happen when you start routing your custom user model to a separate database and try to access that user database from another django application to build up a centralized user database for several applications with direct access and no protocol overhead like rest-api or such involved. – Torsten Aug 20 '21 at 19:03
0

I've encountered this when upgrading to django 3.1. That is the version that adds the auth.0012 migration.

The issue:

My app's initial migration had the following dependencies:

dependencies = [
    ('contenttypes', '__latest__'),
    ('auth', '__latest__'),
    ...
]

Since the latest auth migration now was auth.0012 which had not been applied, the dependencies for the app were unfulfilled and the migration fails:

django.db.migrations.exceptions.InconsistentMigrationHistory: Migration dbentry.0001_initial is applied before its dependency auth.0012_alter_user_first_name_max_length on database 'default'

The fix:

Set auth dependency to the latest migration that had already been applied: ('auth', '0011_update_proxy_permissions') in my case. The migrations will then run and apply auth.0012. At that point, you can set the dependency back to __latest__ - though that could mean having to repeat this process the next time django.auth adds a migration.

CoffeeBasedLifeform
  • 2,296
  • 12
  • 27