Makemigrations django error

I was trying to create migrations within an existing app using the makemigrations command but it outputs "No changes detected". Usually I create new apps using the startapp command but did not use...

To create initial migrations for an app, run makemigrations and specify the app name. The migrations folder will be created.

./manage.py makemigrations <myapp>

Your app must be included in INSTALLED_APPS first (inside settings.py).

hestellezg's user avatar

hestellezg

3,0593 gold badges31 silver badges35 bronze badges

answered Mar 22, 2016 at 12:19

Alasdair's user avatar

AlasdairAlasdair

291k53 gold badges563 silver badges507 bronze badges

7

My problem (and so solution) was yet different from those described above.

I wasn’t using models.py file, but created a models directory and created the my_model.py file there, where I put my model. Django couldn’t find my model so it wrote that there are no migrations to apply.

My solution was: in the my_app/models/__init__.py file I added this line:
from .my_model import MyModel

answered Dec 10, 2017 at 15:03

Karina Klinkevičiūtė's user avatar

7

There are multiple possible reasons for django not detecting what to migrate during the makemigrations command.

  1. migration folder You need a migrations package in your app.
  2. INSTALLED_APPS You need your app to be specified in the INSTALLED_APPS .dict
  3. Verbosity start by running makemigrations -v 3 for verbosity. This might shed some light on the problem.
  4. Full path In INSTALLED_APPS it is recommended to specify the full module app config path ‘apply.apps.MyAppConfig’
  5. —settings you might want to make sure the correct settings file is set: manage.py makemigrations --settings mysite.settings
  6. specify app name explicitly put the app name in manage.py makemigrations myapp — that narrows down the migrations for the app alone and helps you isolate the problem.
  7. model meta check you have the right app_label in your model meta

  8. Debug django debug django core script. makemigrations command is pretty much straight forward. Here’s how to do it in pycharm. change your script definition accordingly (ex: makemigrations --traceback myapp)

Multiple databases:

  • Db Router when working with django db router, the router class (your custom router class) needs to implement the allow_syncdb method.

makemigrations always creates migrations for model changes, but if
allow_migrate() returns False,

answered Mar 22, 2018 at 11:21

user1134422's user avatar

user1134422user1134422

1,1018 silver badges7 bronze badges

8

I’ve read many answers to this question often stating to simply run makemigrations in some other ways. But to me, the problem was in the Meta subclass of models.

I have an app config that says label = <app name> (in the apps.py file, beside models.py, views.py etc). If by any chance your meta class doesn’t have the same label as the app label (for instance because you are splitting one too big app into multiple ones), no changes are detected (and no helpful error message whatsoever). So in my model class I have now:

class ModelClassName(models.Model):

    class Meta:
        app_label = '<app name>' # <-- this label was wrong before.

    field_name = models.FloatField()
    ...

Running Django 1.10 here.

answered Mar 25, 2017 at 8:28

onekiloparsec's user avatar

1

Another thing that will cause this is a trailing comma after the field which will cause the field to skipped during makemigrations:

class MyModel(models.Model):
    name = models.CharField(max_length=64, null=True)  # works
    language_code = models.CharField(max_length=2, default='en')  # works
    is_dumb = models.BooleanField(default=False),  # doesn't work

I had a trailing , in one line perhaps from copy&paste. The line with is_dumb doesn’t create a model migration with ./manage.py makemigrations because Python thinks it is a tuple, and Django doesn’t consider it a field.

Ben Davis's user avatar

Ben Davis

12.6k10 gold badges48 silver badges58 bronze badges

answered Sep 11, 2018 at 17:03

yvess's user avatar

yvessyvess

1,94218 silver badges17 bronze badges

3

It is a comment but should probably be an answer.

Make sure that your app name is in settings.py INSTALLED_APPS otherwise no matter what you do it will not run the migrations.

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    'blog',
]

Then run:

./manage.py makemigrations blog

answered Sep 22, 2017 at 9:16

tread's user avatar

treadtread

9,69917 gold badges90 silver badges158 bronze badges

2

Method : 1

Step : 1

Make sure your app must be included in INSTALLED_APPS in settings.py

Stpe : 2

python manage.py makemigrations <appname>

if same message shows (No changes detected)

!Warning This is Very Risky For Your Project So Make Sure You Have Backup For Your Project Before Applying The Method 2.

Method 2

rename your app name and make new app using :

django-admin startapp <appname>

copy all .py files except from the old app

  • migration folder
  • pycache folder
  • init.py
  • test.py file if you didn’t wrote code in it

and paste into the new app which you made recently

remember you have to make exact the same name for new app otherwise you have to make more changes in the project.

answered Jul 20, 2021 at 11:36

Sushang Agnihotri's user avatar

update: One should make sure that an __init__.py file exists in the migrations folder before trying:

./manage.py makemigrations <myapp1> <myapp2> ... <myappN>


There are sometimes when ./manage.py makemigrations is superior to ./manage.py makemigrations <myapp> because it can handle certain conflicts between apps.

Those occasions occur silently and it takes several hours of swearing to understand the real meaning of the dreaded No changes detected message.

Therefore, it is a far better choice to make use of the following command:

./manage.py makemigrations <myapp1> <myapp2> ... <myappN>

answered May 1, 2016 at 22:56

raratiru's user avatar

raratiruraratiru

8,3184 gold badges70 silver badges109 bronze badges

0

  1. Make sure your app is mentioned in installed_apps in settings.py
  2. Make sure you model class extends models.Model

answered Aug 8, 2019 at 18:31

Amandeep Singh's user avatar

My problem was much simpler than the above answers and probably a far more common reason as long as your project is already set up and working. In one of my applications that had been working for a long time, migrations seemed wonky, so in a hurry, I did the following:

rm -r */migrations/*
rm db.sqlite3
python3 manage.py makemigrations
No changes detected

Whaat??

I had mistakenly also removed all the __init__.py files :( — Everything was working again after I went in and:

touch ads1/migrations/__init__.py

For each of my applications then the makemigrations worked again.

It turns out that I had manually created a new application by copying another and forgot to put the __init__.py in the migrations folder and that confinved me that everything was wonky — leading my making it worse with an rm -r as described above.

Hope this helps someone from swearing at the «No changes detected» error for a few hours.

answered Nov 23, 2019 at 20:08

drchuck's user avatar

drchuckdrchuck

4,2453 gold badges27 silver badges30 bronze badges

I had copied a table in from outside of django and the Meta class defaulted to «managed = false». For example:

class Rssemailsubscription(models.Model):
    id = models.CharField(primary_key=True, max_length=36)
    ...
    area = models.FloatField('Area (Sq. KM)', null=True)

    class Meta:
        managed = False
        db_table = 'RSSEmailSubscription'

By changing managed to True, makemigrations started picking up changes.

Mike Slinn's user avatar

Mike Slinn

7,4385 gold badges50 silver badges84 bronze badges

answered Jul 28, 2018 at 21:46

Dan Cogswell's user avatar

Another possible reason is if you had some models defined in another file (not in a package) and haven’t referenced that anywhere else.

For me, simply adding from .graph_model import * to admin.py (where graph_model.py was the new file) fixed the problem.

answered Oct 31, 2019 at 4:51

Nick Lothian's user avatar

Nick LothianNick Lothian

1,3991 gold badge14 silver badges27 bronze badges

When adding new models to the django api application and running the python manage.py makemigrations the tool did not detect any new models.

The strange thing was that the old models did got picked by makemigrations, but this was because they were referenced in the urlpatterns chain and the tool somehow detected them. So keep an eye on that behavior.

The problem was because the directory structure corresponding to the models package had subpackages and all the __init__.py files were empty. They must explicitly import all the required classes in each subfolder and in the models __init__.py for Django to pick them up with the makemigrations tool.

models
  ├── __init__.py          <--- empty
  ├── patient
  │   ├── __init__.py      <--- empty
  │   ├── breed.py
  │   └── ...
  ├── timeline
  │   ├── __init__.py      <-- empty
  │   ├── event.py
  │   └── ...

answered Apr 15, 2020 at 13:55

atoledo's user avatar

atoledoatoledo

3852 silver badges11 bronze badges

This might hopefully help someone else, as I ended up spending hours trying to chase this down.

If you have a function within your model by the same name, this will remove the value. Pretty obvious in hindsight, but nonetheless.

So, if you have something like this:

class Foobar(models.Model):
    [...]
    something = models.BooleanField(default=False)

    [...]
    def something(self):
        return [some logic]

In that case, the function will override the setting above, making it «invisible» to makemigrations.

answered Jun 9, 2020 at 16:06

vpetersson's user avatar

vpeterssonvpetersson

1,5602 gold badges15 silver badges17 bronze badges

A very dumb issue you can have as well is to define two class Meta in your model. In that case, any change to the first one won’t be applied when running makemigrations.

class Product(models.Model):
    somefield = models.CharField(max_length=255)
    someotherfield = models.CharField(max_length=255)

    class Meta:
        indexes = [models.Index(fields=["somefield"], name="somefield_idx")]

    def somefunc(self):
        pass

    # Many lines...

    class Meta:
        indexes = [models.Index(fields=["someotherfield"], name="someotherfield_idx")]

answered Apr 2, 2019 at 13:57

nbeuchat's user avatar

nbeuchatnbeuchat

6,3275 gold badges36 silver badges49 bronze badges

In my case i forgot to insert the class arguments

Wrong:

class AccountInformation():

Correct

class AccountInformation(models.Model):

answered Dec 3, 2019 at 7:23

JSRB's user avatar

JSRBJSRB

2,4871 gold badge14 silver badges43 bronze badges

1

I had a different issue while creating a new app called deals. I wanted to separate the models inside that app so I had 2 model files named deals.py and dealers.py.
When running python manage.py makemigrations I got: No changes detected.

I went ahead and inside the __init__.py which lives on the same directory where my model files lived (deals and dealer) I did

from .deals import *
from .dealers import *

And then the makemigrations command worked.

Turns out that if you are not importing the models anywhere OR your models file name isn’t models.py then the models wont be detected.

Another issue that happened to me is the way I wrote the app in settings.py:

I had:

apps.deals

It should’ve been including the root project folder:

cars.apps.deals

answered May 27, 2020 at 17:55

elad silver's user avatar

elad silverelad silver

8,8624 gold badges43 silver badges66 bronze badges

I solved that problem by doing this:

  1. Erase the «db.sqlite3» file. The issue here is that your current data base will be erased, so you will have to remake it again.
  2. Inside the migrations folder of your edited app, erase the last updated file. Remember that the first created file is: «0001_initial.py». For example: I made a new class and register it by the «makemigrations» and «migrate» procedure, now a new file called «0002_auto_etc.py» was created; erase it.
  3. Go to the «pycache» folder (inside the migrations folder) and erase the file «0002_auto_etc.pyc».
  4. Finally, go to the console and use «python manage.py makemigrations» and «python manage.py migrate».

answered Oct 23, 2018 at 16:33

Juan David Argüello Plata's user avatar

I know this is an old question but I fought with this same issue all day and my solution was a simple one.

I had my directory structure something along the lines of…

apps/
   app/
      __init__.py
      app_sub1/
           __init__.py
           models.py
      app_sub2/
           __init__.py
           models.py
      app_sub3/
           __init__.py
           models.py
   app2/
      __init__.py
      app2_sub1/
           __init__.py
           models.py
      app2_sub2/
           __init__.py
           models.py
      app2_sub3/
           __init__.py
           models.py
    main_app/
      __init__.py
      models.py

And since all the other models up until the one I had a problem with were being imported somewhere else that ended up importing from main_app which was registered in the INSTALLED_APPS, I just got lucky that they all worked.

But since I only added each app to INSTALLED_APPS and not the app_sub* when I finally added a new models file that wasn’t imported ANYWHERE else, Django totally ignored it.

My fix was adding a models.py file to the base directory of each app like this…

apps/
   app/
      __init__.py
      models.py <<<<<<<<<<--------------------------
      app_sub1/
           __init__.py
           models.py
      app_sub2/
           __init__.py
           models.py
      app_sub3/
           __init__.py
           models.py
   app2/
      __init__.py
      models.py <<<<<<<<<<--------------------------
      app2_sub1/
           __init__.py
           models.py
      app2_sub2/
           __init__.py
           models.py
      app2_sub3/
           __init__.py
           models.py
    main_app/
      __init__.py
      models.py

and then add from apps.app.app_sub1 import * and so on to each of the app level models.py files.

Bleh… this took me SO long to figure out and I couldn’t find the solution anywhere… I even went to page 2 of the google results.

Hope this helps someone!

answered May 12, 2019 at 1:27

Tim's user avatar

I forgot to put correct arguments:

class LineInOffice(models.Model):   # here
    addressOfOffice = models.CharField("Корхоная жош",max_length= 200)   #and here
    ...

in models.py
and then it started to drop that annoying

No changes detected in app ‘myApp ‘

answered Sep 19, 2019 at 21:09

CodeToLife's user avatar

CodeToLifeCodeToLife

3,4592 gold badges39 silver badges28 bronze badges

INSTALLED_APPS = [

    'blog.apps.BlogConfig',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',

]

make sure ‘blog.apps.BlogConfig’, (this is included in your settings.py in order to make your app migrations)

then run python3 manage.py makemigrations blog or your app name

Marlon Abeykoon's user avatar

answered Mar 23, 2019 at 3:28

Piyush Chandra's user avatar

This could be done by using two steps that are mentioned below.

  1. add your app to settings.py > INSTALLED_APPS
  2. open admin.py

from .models import upImg
# Register your models here.
admin.site.register(upImg)

NOTE: replace upImg with your className defined in models.py

after that see if there still any python manage.py makemigrations are left or not. if there is, than execute python manage.py migrate too.

For more info follow this django tutorial.

David Lee's user avatar

answered Jul 11, 2021 at 4:05

Navjot Kashi's user avatar

The solution is you have to include your app in INSTALLED_APPS.

I missed it and I found this same issue.

after specifying my app name migration became successful

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'boards',
]

please note I mentioned boards in last, which is my app name.

answered Sep 29, 2018 at 17:02

sradha's user avatar

sradhasradha

2,1961 gold badge26 silver badges47 bronze badges

One more edge case and solution:

I added a boolean field, and at the same time added an @property referencing it, with the same name (doh). Commented the property and migration sees and adds the new field. Renamed the property and all is good.

answered Mar 2, 2020 at 16:17

kgeo's user avatar

kgeokgeo

3804 silver badges18 bronze badges

Try registering your model in admin.py, here’s an example:-
admin.site.register(YourModelHere)

You can do the following things:-
1. admin.site.register(YourModelHere) # In admin.py
2. Reload the page and try again
3. Hit CTRL-S and save
4. There might be an error, specially check models.py and admin.py
5. Or, at the end of it all just restart the server

answered Jun 4, 2020 at 20:54

GURU RAJ's user avatar

I had a similar issue with django 3.0, according migrations section in the official documentation, running this was enough to update my table structure:

python manage.py makemigrations
python manage.py migrate

But the output was always the same: ‘no change detected’ about my models after I executed ‘makemigrations’ script.
I had a syntax error on models.py at the model I wanted to update on db:

field_model : models.CharField(max_length=255, ...)

instead of:

field_model = models.CharField(max_length=255, ...)

Solving this stupid mistake, with those command the migration was done without problems. Maybe this helps someone.

answered Jun 7, 2020 at 23:09

Yair Abad's user avatar

Yair AbadYair Abad

1863 silver badges5 bronze badges

1

My problem with this error, was that I had included:

class Meta:
   abstract = True

Inside model that I wanted to creation migrate for.

answered Jun 21, 2020 at 16:36

Dolidod Teethtard's user avatar

Its easy, you need to add empty init.py in empty migrations folder.
Then check migrations using «python manage.py makemigrations»

Directory structure-

  • Your App
    • migrations
      • init.py

answered Aug 5, 2022 at 11:17

Ruturaj Singare's user avatar

1

You should add polls.apps.PollsConfig to INSTALLED_APPS in setting.py

Derk Jan Speelman's user avatar

answered Mar 20, 2019 at 16:08

Kitty's user avatar

The possible reason could be deletion of the existing db file and migrations folder
you can use python manage.py makemigrations <app_name> this should work. I once faced a similar problem.

tahesse's user avatar

tahesse

1,40815 silver badges31 bronze badges

answered Mar 1, 2020 at 11:44

Akash G Krishnan's user avatar

1

I was trying to create migrations within an existing app using the makemigrations command but it outputs «No changes detected».

Usually I create new apps using the startapp command but did not use it for this app when I created it.

After debugging, I found that it is not creating migration because the migrations package/folder is missing from an app.

Would it be better if it creates the folder if it is not there or am I missing something?

1) Solution

To create initial migrations for an app, run makemigrations and specify the app name. The migrations folder will be created.

./manage.py makemigrations <myapp>

Your app must be included in INSTALLED_APPS first (inside settings.py).

2) Solution

My problem (and so solution) was yet different from those described above.

I wasn’t using models.py file, but created a models directory and created the my_model.py file there, where I put my model. Django couldn’t find my model so it wrote that there are no migrations to apply.

My solution was: in the my_app/models/__init__.py file I added this line:
from .my_model import MyModel

3) Solution

There are multiple possible reasons for django not detecting what to migrate during the makemigrations command.

  1. migration folder You need a migrations package in your app.
  2. INSTALLED_APPS You need your app to be specified in the INSTALLED_APPS .dict
  3. Verbosity start by running makemigrations -v 3 for verbosity. This might shed some light on the problem.
  4. Full path In INSTALLED_APPS it is recommended to specify the full module app config path ‘apply.apps.MyAppConfig’
  5. —settings you might want to make sure the correct settings file is set: manage.py makemigrations --settings mysite.settings
  6. specify app name explicitly put the app name in manage.py makemigrations myapp — that narrows down the migrations for the app alone and helps you isolate the problem.
  7. model meta check you have the right app_label in your model meta

  8. Debug django debug django core script. makemigrations command is pretty much straight forward. Here’s how to do it in pycharm. change your script definition accordingly (ex: makemigrations --traceback myapp)

Multiple databases:

  • Db Router when working with django db router, the router class (your custom router class) needs to implement the allow_syncdb method.

makemigrations always creates migrations for model changes, but if
allow_migrate() returns False,

4) Solution

I’ve read many answers to this question often stating to simply run makemigrations in some other ways. But to me, the problem was in the Meta subclass of models.

I have an app config that says label = <app name> (in the apps.py file, beside models.py, views.py etc). If by any chance your meta class doesn’t have the same label as the app label (for instance because you are splitting one too big app into multiple ones), no changes are detected (and no helpful error message whatsoever). So in my model class I have now:

class ModelClassName(models.Model):

    class Meta:
        app_label = '<app name>' # <-- this label was wrong before.

    field_name = models.FloatField()
    ...

Running Django 1.10 here.

5) Solution

I had another problem not described here, which drove me nuts.

class MyModel(models.Model):
    name = models.CharField(max_length=64, null=True)  # works
    language_code = models.CharField(max_length=2, default='en')  # works
    is_dumb = models.BooleanField(default=False),  # doesn't work

I had a trailing ‘,’ in one line perhaps from copy&paste. The line with is_dumb doesn’t created a model migration with ‘./manage.py makemigrations’ but also didn’t throw an error. After removing the ‘,’ it worked as expected.

So be careful when you do copy&paste :-)

6) Solution

It is a comment but should probably be an answer.

Make sure that your app name is in settings.py INSTALLED_APPS otherwise no matter what you do it will not run the migrations.

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    'blog',
]

Then run:

./manage.py makemigrations blog
7) Solution
  1. Make sure your app is mentioned in installed_apps in settings.py
  2. Make sure you model class extends models.Model
8) Solution

There are sometimes when ./manage.py makemigrations is superior to ./manage.py makemigrations <myapp> because it can handle certain conflicts between apps.

Those occasions occur silently and it takes several hours of swearing to understand the real meaning of the dreaded No changes detected message.

Therefore, it is a far better choice to make use of the following command:

./manage.py makemigrations <myapp1> <myapp2> ... <myappN>

9) Solution

I had copied a table in from outside of django and the Meta class defaulted to «managed = false». For example:

class Rssemailsubscription(models.Model):
    id = models.CharField(primary_key=True, max_length=36)
    ...
    area = models.FloatField('Area (Sq. KM)', null=True)

    class Meta:
        managed = False
        db_table = 'RSSEmailSubscription'

By changing managed to True, makemigrations started picking up changes.

10) Solution

My problem was much simpler than the above answers and probably a far more common reason as long as your project is already set up and working. In one of my applications that had been working for a long time, migrations seemed wonky, so in a hurry, I did the following:

rm -r */migrations/*
rm db.sqlite3
python3 manage.py makemigrations
No changes detected

Whaat??

I had mistakenly also removed all the __init__.py files :( — Everything was working again after I went in and:

touch ads1/migrations/__init__.py

For each of my applications then the makemigrations worked again.

It turns out that I had manually created a new application by copying another and forgot to put the __init__.py in the migrations folder and that confinved me that everything was wonky — leading my making it worse with an rm -r as described above.

Hope this helps someone from swearing at the «No changes detected» error for a few hours.

11) Solution

Method : 1

Step : 1

Make sure your app must be included in INSTALLED_APPS in settings.py

Stpe : 2

python manage.py makemigrations <appname>

if same message shows (No changes detected)

!Warning This is Very Risky For Your Project So Make Sure You Have Backup For Your Project Before Applying The Method 2.

Method 2

rename your app name and make new app using :

django-admin startapp <appname>

copy all .py files except from the old app

  • migration folder
  • pycache folder
  • init.py
  • test.py file if you didn’t wrote code in it

and paste into the new app which you made recently

remember you have to make exact the same name for new app otherwise you have to make more changes in the project.

12) Solution

Another possible reason is if you had some models defined in another file (not in a package) and haven’t referenced that anywhere else.

For me, simply adding from .graph_model import * to admin.py (where graph_model.py was the new file) fixed the problem.

13) Solution

This might hopefully help someone else, as I ended up spending hours trying to chase this down.

If you have a function within your model by the same name, this will remove the value. Pretty obvious in hindsight, but nonetheless.

So, if you have something like this:

class Foobar(models.Model):
    [...]
    something = models.BooleanField(default=False)

    [...]
    def something(self):
        return [some logic]

In that case, the function will override the setting above, making it «invisible» to makemigrations.

14) Solution

When adding new models to the django api application and running the python manage.py makemigrations the tool did not detect any new models.

The strange thing was that the old models did got picked by makemigrations, but this was because they were referenced in the urlpatterns chain and the tool somehow detected them. So keep an eye on that behavior.

The problem was because the directory structure corresponding to the models package had subpackages and all the __init__.py files were empty. They must explicitly import all the required classes in each subfolder and in the models __init__.py for Django to pick them up with the makemigrations tool.

models
  ├── __init__.py          <--- empty
  ├── patient
  │   ├── __init__.py      <--- empty
  │   ├── breed.py
  │   └── ...
  ├── timeline
  │   ├── __init__.py      <-- empty
  │   ├── event.py
  │   └── ...
15) Solution

A very dumb issue you can have as well is to define two class Meta in your model. In that case, any change to the first one won’t be applied when running makemigrations.

class Product(models.Model):
    somefield = models.CharField(max_length=255)
    someotherfield = models.CharField(max_length=255)

    class Meta:
        indexes = [models.Index(fields=["somefield"], name="somefield_idx")]

    def somefunc(self):
        pass

    # Many lines...

    class Meta:
        indexes = [models.Index(fields=["someotherfield"], name="someotherfield_idx")]
16) Solution

I had a different issue while creating a new app called deals. I wanted to separate the models inside that app so I had 2 model files named deals.py and dealers.py.
When running python manage.py makemigrations I got: No changes detected.

I went ahead and inside the __init__.py which lives on the same directory where my model files lived (deals and dealer) I did

from .deals import *
from .dealers import *

And then the makemigrations command worked.

Turns out that if you are not importing the models anywhere OR your models file name isn’t models.py then the models wont be detected.

Another issue that happened to me is the way I wrote the app in settings.py:

I had:

apps.deals

It should’ve been including the root project folder:

cars.apps.deals
17) Solution

I forgot to put correct arguments:

class LineInOffice(models.Model):   # here
    addressOfOffice = models.CharField("Корхоная жош",max_length= 200)   #and here
    ...

in models.py
and then it started to drop that annoying

No changes detected in app ‘myApp ‘

18) Solution

I solved that problem by doing this:

  1. Erase the «db.sqlite3» file. The issue here is that your current data base will be erased, so you will have to remake it again.
  2. Inside the migrations folder of your edited app, erase the last updated file. Remember that the first created file is: «0001_initial.py». For example: I made a new class and register it by the «makemigrations» and «migrate» procedure, now a new file called «0002_auto_etc.py» was created; erase it.
  3. Go to the «pycache» folder (inside the migrations folder) and erase the file «0002_auto_etc.pyc».
  4. Finally, go to the console and use «python manage.py makemigrations» and «python manage.py migrate».
19) Solution

I know this is an old question but I fought with this same issue all day and my solution was a simple one.

I had my directory structure something along the lines of…

apps/
   app/
      __init__.py
      app_sub1/
           __init__.py
           models.py
      app_sub2/
           __init__.py
           models.py
      app_sub3/
           __init__.py
           models.py
   app2/
      __init__.py
      app2_sub1/
           __init__.py
           models.py
      app2_sub2/
           __init__.py
           models.py
      app2_sub3/
           __init__.py
           models.py
    main_app/
      __init__.py
      models.py

And since all the other models up until the one I had a problem with were being imported somewhere else that ended up importing from main_app which was registered in the INSTALLED_APPS, I just got lucky that they all worked.

But since I only added each app to INSTALLED_APPS and not the app_sub* when I finally added a new models file that wasn’t imported ANYWHERE else, Django totally ignored it.

My fix was adding a models.py file to the base directory of each app like this…

apps/
   app/
      __init__.py
      models.py <<<<<<<<<<--------------------------
      app_sub1/
           __init__.py
           models.py
      app_sub2/
           __init__.py
           models.py
      app_sub3/
           __init__.py
           models.py
   app2/
      __init__.py
      models.py <<<<<<<<<<--------------------------
      app2_sub1/
           __init__.py
           models.py
      app2_sub2/
           __init__.py
           models.py
      app2_sub3/
           __init__.py
           models.py
    main_app/
      __init__.py
      models.py

and then add from apps.app.app_sub1 import * and so on to each of the app level models.py files.

Bleh… this took me SO long to figure out and I couldn’t find the solution anywhere… I even went to page 2 of the google results.

Hope this helps someone!

20) Solution

In my case i forgot to insert the class arguments

Wrong:

class AccountInformation():

Correct

class AccountInformation(models.Model):
21) Solution

This could be done by using two steps that are mentioned below.

  1. add your app to settings.py > INSTALLED_APPS
  2. open admin.py

from .models import upImg
# Register your models here.
admin.site.register(upImg)

NOTE: replace upImg with your className defined in models.py

after that see if there still any python manage.py makemigrations are left or not. if there is, than execute python manage.py migrate too.

For more info follow this django tutorial.

22) Solution
INSTALLED_APPS = [

    'blog.apps.BlogConfig',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',

]

make sure ‘blog.apps.BlogConfig’, (this is included in your settings.py in order to make your app migrations)

then run python3 manage.py makemigrations blog or your app name

23) Solution

I had a similar issue with django 3.0, according migrations section in the official documentation, running this was enough to update my table structure:

python manage.py makemigrations
python manage.py migrate

But the output was always the same: ‘no change detected’ about my models after I executed ‘makemigrations’ script.
I had a syntax error on models.py at the model I wanted to update on db:

field_model : models.CharField(max_length=255, ...)

instead of:

field_model = models.CharField(max_length=255, ...)

Solving this stupid mistake, with those command the migration was done without problems. Maybe this helps someone.

24) Solution

Try registering your model in admin.py, here’s an example:-
admin.site.register(YourModelHere)

You can do the following things:-
1. admin.site.register(YourModelHere) # In admin.py
2. Reload the page and try again
3. Hit CTRL-S and save
4. There might be an error, specially check models.py and admin.py
5. Or, at the end of it all just restart the server

25) Solution

One more edge case and solution:

I added a boolean field, and at the same time added an @property referencing it, with the same name (doh). Commented the property and migration sees and adds the new field. Renamed the property and all is good.

26) Solution

The solution is you have to include your app in INSTALLED_APPS.

I missed it and I found this same issue.

after specifying my app name migration became successful

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'boards',
]

please note I mentioned boards in last, which is my app name.

27) Solution

If you have the managed = True in yout model Meta, you need to remove it and do a migration. Then run the migrations again, it will detect the new updates.

28) Solution

You should add polls.apps.PollsConfig to INSTALLED_APPS in setting.py

29) Solution

My problem with this error, was that I had included:

class Meta:
   abstract = True

Inside model that I wanted to creation migrate for.

30) Solution

The possible reason could be deletion of the existing db file and migrations folder
you can use python manage.py makemigrations <app_name> this should work. I once faced a similar problem.

Comments Section

Do you have your app added to INSTALLED_APPS?

Yes it is in installed app, for the first time , better to be use makemigrations <myapp> as Alasdair pointed out also.

Any idea why they <sometimes> force us to specify the app ?

@maazza you need to specify the app name if the app does not have migrations folder. This could happen if you created the app manually, or you have upgraded from an older version of Django that didn’t have migrations.

Remove ‘abstract = True’ :)

@maazza Actually you need a python package (with __init__.py) named ‘migrations’ in the app.

Sounds like something that Django should handle automatically.

@duality_ this is by design — Django doesn’t assume that you want migrations for your app. If it created migrations for all apps, it could lead to errors when you run migrate.

Covered many scenarios regarding the problem, should be the accepted answer.

but it creates the table name as ‘appname_modelname’, when we run ‘manage.py migrate’ command

See model meta options to change the table name

This happended to be the solution for me as well, but I do not understand why this is. Does anyone have some insight as to what may be causing this?

Django has a default paths of where to look for your models. If the project structure is different, and the models are not in the usual place, they need to be imported there.

Another possibility: The wrong name is being imported, i.e. importing a field from forms instead of fields, or importing a model from forms instead of models. An example: from recurrence.forms import RecurrenceField but it should have been from recurrence.fields import RecurrenceField.

The trailing comma can cause bugs elsewhere as well; the comma makes the statement a tuple, so is_dumb is equal to (models.BooleanField(default=False), ) which makemigrations doesn’t know how to convert into a database column.

‘makemigrations’ did not work. ‘makemigrations <myapp>’ worked

@KarinaKlinkevičiūtė what if I need to remove such models?

@DaniilMashkin I imagine you would need to remove imports also. This is one of the ways of structuring your project (not the only one) and you have to deal with additional tasks that comes with it if you choose it :)

I used the «classic» architecture for models, then I migrated to the «models folder» architecture, and any migration is still detected on my existing models. However, now, when creating a new model, I have this issue. Your solution works well, but it let my codebase kind of inconsistent because sometimes there is an import, sometimes not. Maybe there is a better solution. I guess Django should propose a settings with a list of folders to look for when trying to find new models.

One more reason. Make sure that the model is used within a route for the website (via admin or otherwise). «The makemigrations script looks for models which are connected from urls.py«. Found here stackoverflow.com/questions/43093651/…

cmd example: python manage.py makemigrations -v 3 <app_name>

When I add a table, and then add a Foreign Key reference this new table at same time. It has to be divided to 2 steps: pre step: add INSTALLED_APPS to settings. 1) create new table: python manage.py makemigrations <app_name> ; 2) add Foreign Key: python manage.py makemigrations

What happens if you don’t have a Meta at all? What value does it assume for app_label then as a default?

This worked for me. I think this one depends on the python version.

I had the same issue, and it was because I forgot to register the model in app/admin.py.

this happened to me, should be a warning if it doesn’t know what to do

I feel like Django should give more warning when you’ve got a messed up model. This fixed my issue too.

Related Topics
python
django
django-migrations

Mentions
Mike Slinn
Tim
Onekiloparsec
Yvess
Alasdair
Dilraj
Hestellezg
Tread
Amandeep Singh
Raratiru
Drchuck
Dan Cogswell
Sushang Agnihotri
Nick Lothian
Vpetersson
Nbeuchat
Atoledo
Elad Silver
Code To Life
Jonas
Marlon Abeykoon
Piyush Chandra
David Lee
Navjot Kashi
Sradha
Kgeo
Guru Raj
Yair Abad
Derk Jan Speelman
Kitty
Tahesse
Akash G Krishnan
Irshu
Dolidod Teethtard
Ben Davis
Jsrb

References
36153748/django-makemigrations-no-changes-detected

Python’s Django web framework abstracts away much of the complexity when building web applications. One of its key facets is the ability to dynamically interact with a given database on a user’s behalf.

Still, any developer needs to understand what’s going on behind the scenes, or it could lead to catastrophic consequences.

In this tutorial, you’ll work closely with Django migrations to manage a SQL database and learn how to troubleshoot costly mistakes.

What is Django?

Django is a popular web framework that allows developers to quickly spin up a web application. Touted as “the web framework for perfectionists with deadlines,” Django takes care of many low-level functions that can slow the development process.

Django offers out-of-the-box capabilities for routing URLs, authenticating users, and interfacing with databases. This is particularly useful for those who have little to no experience with Structured Query Language (SQL).

SQL is a domain-specific programming language that is used to interact with a relational database management system. Using SQL, one can create, read, update, and remove the records in a given database. However, the intricacies of SQL can be quite complex, and running improper queries can quickly result in the loss of sensitive or irretrievable data.

Django solves this problem by using an object-relational mapper to interface with the database on your behalf. In other words, you tell Django what structure you want the database to have, and Django takes care of translating your Python instructions to SQL queries to be executed on your chosen database. While you can still write SQL if needed, you don’t have to: you simply define your data models in Python, and Django takes care of the rest.

Here’s an example of a Django data model:

class Rocket(models.Model):
    """A model of a rocket ship."""
    name = models.CharField(max_length=200)
    launch_date = models.DateField()
    ready_to_launch = models.BooleanField(default=True)

This data model defines the structure for a database table called Rocket. The model states that the Rocket table should have three columns: name, launch_date, and ready_to_launch.

Note that this data model doesn’t specify an index or a row counter; that’s because Django implements this automatically under the hood.

Once you’re ready, you’ll pass this data model off to Django, where it will be transformed into the following database table:

id name launch_date ready_to_launch
1 Apollo 2035-10-19 False
2 Orion 2022-04-05 True

The fields of your data model correspond to the headers in your database table. This table has been populated with data, and Django has automatically created a new id for each row.

What is a migration?

So, how exactly does Django translate your Python model into a database table? Surely defining a table structure as a data model isn’t all there is to it.

Well, in order to go from data model to database table, you’ll need a migration. This is a special type of Python file that contains the instructions that Django needs to create the database table on your behalf.

Django uses your data model to populate these instructions and then runs a migrate command to apply those changes to the database.

In short, Django migrations follow two key steps:

  1. Create a migration file containing instructions for altering the database table
  2. Migrate the database table by running the code contained in the migration file

This two-step process ensures that only the changes you explicitly want to be made are applied. If a migration file contains an error or is missing a critical field, you’re able to correct the issue before applying the changes to the database itself.

This process makes it extremely simple for even junior web developers to interact with a robust database management system. There’s no need for complex SQL queries or to use a browser-based management console to change the database.

Simply define your data models, migrate your changes, and you’re good to go! Migrations are an excellent example of Django’s rapid prototyping capabilities.

Setting up a Django project

Let’s initialize our project by creating a new folder and activating a virtual environment:

$ mkdir django-migrations-tutorial
$ cd django-migrations-tutorial
$ python3 -m venv django-tut
$ source django-tut/bin/activate

The source django-tut/bin/activate command will activate the django-tut virtual environment on Linux or macOS. If you’re on Windows, the command will look slightly different:

django-tut/bin/activate.

Inside of your virtual environment, install the latest version of Django:

(django-tut) $ python3 -m pip install django

Now that you have Django installed, you can start a new project using the startproject command. Let’s name our project log_rocket:

(django-tut) $ django-admin startproject log_rocket.

The trailing period tells Django to install the project inside the current directory. Here’s what the project directory looks like now (excluding the virtual environment directory):

(django-tut) $ tree
.
├── log_rocket
│   ├── asgi.py
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
└── manage.py

1 directory, 6 files

Performing Django migrations

Because Django acts as a scaffold to help you bootstrap your web development, it comes prepackaged with several internal data models and will automatically create a SQLite database for you when you apply an initial migration.

To migrate Django’s internal data models and create the initial database, you’ll use the migrate management command:

(django-tut) $ python3 manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying admin.0001_initial... OK
  Applying admin.0002_logentry_remove_auto_add... OK
  Applying admin.0003_logentry_add_action_flag_choices... OK
  Applying contenttypes.0002_remove_content_type_name... OK
  Applying auth.0002_alter_permission_name_max_length... OK
  Applying auth.0003_alter_user_email_max_length... OK
  Applying auth.0004_alter_user_username_opts... OK
  Applying auth.0005_alter_user_last_login_null... OK
  Applying auth.0006_require_contenttypes_0002... OK
  Applying auth.0007_alter_validators_add_error_messages... OK
  Applying auth.0008_alter_user_username_max_length... OK
  Applying auth.0009_alter_user_last_name_max_length... OK
  Applying auth.0010_alter_group_name_max_length... OK
  Applying auth.0011_update_proxy_permissions... OK
  Applying auth.0012_alter_user_first_name_max_length... OK
  Applying sessions.0001_initial... OK

The output should show that Django has successfully run its own internal instructions to create an initial database. Now, if you examine the directory structure again, you should see a new file:

(django-tut) $ tree
.
├── db.sqlite3
├── log_rocket
│   ├── asgi.py
│   ├── __init__.py
│   ├── __pycache__
│   │   ├── __init__.cpython-38.pyc
│   │   ├── settings.cpython-38.pyc
│   │   └── urls.cpython-38.pyc
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
└── manage.py

2 directories, 10 files

At the top of the tree, there’s a new database file, db.sqlite3. This is a SQLite database, which is the default database that Django creates for local development and testing purposes.

You can use the dbshell management command to examine the new database and confirm that Django has created the tables:

(django-tut) $ python3 manage.py dbshell
SQLite version 3.28.0 2019-04-16 19:49:53
Enter ".help" for usage hints.
sqlite>

In the prompt, type .tables to see a list of all the tables in the database:

sqlite> .tables
auth_group                  auth_user_user_permissions
auth_group_permissions      django_admin_log
auth_permission             django_content_type
auth_user                   django_migrations
auth_user_groups            django_session
sqlite> .exit

You can exit the database shell with the .exit command.

Creating migrations for new models

Django comes with a few data models built-in, but you’ll need to define most of them from scratch. In this section, we’ll create a Django app, define a model for it, and migrate your changes to the database.

Previously, we started a Django project called log_rocket. Now, you’ll create an app to attach to this project. A Django project is a directory that contains the global settings needed to manage all apps that are associated with it.


More great articles from LogRocket:

  • Don’t miss a moment with The Replay, a curated newsletter from LogRocket
  • Learn how LogRocket’s Galileo cuts through the noise to proactively resolve issues in your app
  • Use React’s useEffect to optimize your application’s performance
  • Switch between multiple versions of Node
  • Discover how to animate your React app with AnimXYZ
  • Explore Tauri, a new framework for building binaries
  • Compare NestJS vs. Express.js

A Django app is a self-contained chunk of a larger project that focuses on a discrete portion of the whole. For example, a web project may contain a blogging app, a users app, a newsletter app, and more.

Let’s create an app for our project called rockets:

(django-tut) $ python3 manage.py startapp rockets

To tell Django about your new app, add its name to the INSTALLED_APPS setting in your project settings file:

# log_rocket/settings.py
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rockets' # add your new app name here
]

This will create a new directory called rockets alongside your project directory. If you examine the files in this new directory, you’ll see that Django has already provided the files you’ll need to define a new data model:

(django-tut) $ tree rockets/
rockets/
├── admin.py
├── apps.py
├── __init__.py
├── migrations
│   └── __init__.py
├── models.py
├── tests.py
└── views.py

1 directory, 7 files

There’s a models.py file, which you’ll use to define your data model, as well as a migrations/ folder for Django to store the instructions for turning your data models into database tables.

Let’s move the Rocket data model we saw earlier into the models.py file. Open the file in your text editor and paste in the code:

from django.db import models

# Create your models here.
class Rocket(models.Model):
    """A model of a rocket ship."""
    name = models.CharField(max_length=200)
    launch_date = models.DateField()
    ready_to_launch = models.BooleanField(default=True)

Save and close the file. Now, you need to tell Django that you want to make a new table in the database. In other words, you need to make a migrations file for Django to use. Thankfully, Django comes with a handy management command that you can use to do this, called makemigrations:

(django-tut) $ python3 manage.py makemigrations rockets
Migrations for 'rockets':
  rockets/migrations/0001_initial.py
    - Create model Rocket

The output you see is Django confirming that you want to create a migration file for the rockets app, within which you’ve defined a new model named Rocket.

The instructions for this data model are saved in the migrations/ folder, with the file name 0001_initial.py. You can open this file and confirm that the changes Django is going to make match what you’ve specified in your models.py file.

Once you’ve confirmed the instructions are correct, you can tell Django to apply them with the migrate command:

(django-tut) $ python3 manage.py migrate rockets
Operations to perform:
  Apply all migrations: rockets
Running migrations:
  Applying rockets.0001_initial... OK

All migrations were applied successfully. Now, when you open dbshell and examine the list of tables, you should see a new one:

(django-tut) $ python3 manage.py dbshell
SQLite version 3.28.0 2019-04-16 19:49:53
Enter ".help" for usage hints.
sqlite> .tables
auth_group                  django_admin_log
auth_group_permissions      django_content_type
auth_permission             django_migrations
auth_user                   django_session
auth_user_groups            rockets_rocket
auth_user_user_permissions
sqlite> .quit

Django has named the new table rockets_rocket after the name of the app (rockets) and the lowercase name of the model you specified (Rockets).

You can manually add data to the new table using an INSERT SQL query:

sqlite> insert into rockets_rocket (name, launch_date, ready_to_launch) values ("Apollo", "2035-10-19", False);
sqlite> insert into rockets_rocket (name, launch_date, ready_to_launch) values ("Orion", "2022-04-05", True);
sqlite> select * from rockets_rocket;
1|Apollo|2035-10-19|0
2|Orion|2022-04-05|1

Here, you used the same field names that you defined in your Rocket model. Each row is automatically assigned a unique id.

Note that you’ve manually inserted strings into the launch_date column, even though your data model specified that these fields should be date objects. Because you’ve already put strings into the database, you’ll want to update your data model to handle values in this column as character data instead. The next section will walk you through how to do this.

Applying migrations to existing models

It’s highly unlikely that the first time you work on a model will also be the last. More often than not, you’ll need to tweak your models to reflect desired changes to the underlying database.

For instance, the launch_date field now contains string data that was manually inserted into the database. However, in your Rocket data model, you initially decided that this field should contain a date object.

Because it’s easier to manually insert strings into a database, let’s change this field on our model to accept character data:

from django.db import models

# Create your models here.
class Rocket(models.Model):
    """A model of a rocket ship."""
    name = models.CharField(max_length=200)
    launch_date = models.CharField(max_length=200) # Update this line
    ready_to_launch = models.BooleanField(default=True)

Now, run the same commands to tell Django about the change to the data model:

(django-tut) $ python3 manage.py makemigrations rockets
Migrations for 'rockets':
  rockets/migrations/0002_alter_rocket_launch_date.py
    - Alter field launch_date on rocket

Django correctly recognizes that you’ve altered the launch_date field. Because this is what you want to happen, you can apply this migration:

(django-tut) $ python3 manage.py migrate rockets
Operations to perform:
  Apply all migrations: rockets
Running migrations:
  Applying rockets.0002_alter_rocket_launch_date... OK

From this point forward, Django will ensure that all dynamically generated launch dates are rendered as strings.

You can use the dbshell to view the database schema and confirm that this change was made:

sqlite> .schema rockets_rocket
CREATE TABLE IF NOT EXISTS "rockets_rocket" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "name" varchar(200) NOT NULL, "ready_to_launch" bool NOT NULL, "launch_date" varchar(200) NOT NULL);

Here, you can see that the "launch_date" column should contain varchar(200) data, or character data with a length no longer than 200 characters.

Reversing migrations

Let’s say that you’ve decided it was better to have the launch_date rendered as a date object. This will make it easier to schedule rocket launches, as you can take advantage of Python functions like datetime.timedelta(). This means you’ll need to undo that change you just made to the launch_date field in the database.

Once again, Django saves the day by providing you with simple commands that you can use to quickly reverse your changes. To unapply a migration, you’ll need to migrate the database once more, passing in the name of the migration that you want to revert to as an argument.

Django helpfully numbers the migrations for you. Changing the launch_date field was the second migration performed, and it’s named 0002_alter_rocket_launch_date. To undo this change, you’ll want to revert to the first migration, which is named 0001_initial:

(django-tut) $ python3 manage.py migrate rockets 0001_initial
Operations to perform:
  Target specific migration: 0001_initial, from rockets
Running migrations:
  Rendering model states... DONE
  Unapplying rockets.0002_alter_rocket_launch_date... OK

The output confirms that Django has reversed the second migration.

A quick look at the database schema also confirms the reversal:

sqlite> .schema rockets_rocket
CREATE TABLE IF NOT EXISTS "rockets_rocket" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "launch_date" date NOT NULL, "name" varchar(200) NOT NULL, "ready_to_launch" bool NOT NULL);

The type for the "launch_date" column has been set to a date object once again.

Showing migrations

If you want to see a quick overview of what migrations have been applied to a Django project, you can use the showmigrations command to view them all at once:

(django-tut) $ python3 manage.py showmigrations
admin
 [X] 0001_initial
 [X] 0002_logentry_remove_auto_add
 [X] 0003_logentry_add_action_flag_choices
auth
 [X] 0001_initial
 [X] 0002_alter_permission_name_max_length
 [X] 0003_alter_user_email_max_length
 [X] 0004_alter_user_username_opts
 [X] 0005_alter_user_last_login_null
 [X] 0006_require_contenttypes_0002
 [X] 0007_alter_validators_add_error_messages
 [X] 0008_alter_user_username_max_length
 [X] 0009_alter_user_last_name_max_length
 [X] 0010_alter_group_name_max_length
 [X] 0011_update_proxy_permissions
 [X] 0012_alter_user_first_name_max_length
contenttypes
 [X] 0001_initial
 [X] 0002_remove_content_type_name
rockets
 [X] 0001_initial
 [ ] 0002_alter_rocket_launch_date
sessions
 [X] 0001_initial

Look closely at the migrations for the rockets app. Even though you reversed the change to the launch_date field, Django has still kept a record of this migration. Indeed, you can list the contents of the migrations directory and see that the file is still there.

This is an immensely useful feature, as it allows you to reapply a previously reversed migration should you so choose. However, Django will automatically reapply that migration the next time you migrate the entire project, so keep this in mind.

Troubleshooting errors in Django migrations

This section will cover a few errors you might come across while working with Django migrations. The concepts in this section are considered advanced because of the severe potential for critical data loss.

Remember to use datasets that you either have a backup for, or whose data you don’t mind losing completely, while you practice the techniques mentioned in the following sections.

Deleting a migration file

In the previous section, you saw that Django keeps a record of all migrations, even ones you’ve unapplied. Furthermore, you know that if you try to migrate the database again, Django will reapply that migration automatically! How can you stop this from happening?

You might try to delete the migration file and migrate the database from there:

(django-tut) $ rm rockets/migrations/0002_alter_rocket_launch_date.py

This will remove the file that says to change the launch_date field to accept character data instead of a date object.

However, Django will present you with an error message if you try to migrate the database now:

(django-tut) $ python3 manage.py migrate rockets
Operations to perform:
  Apply all migrations: rockets
Running migrations:
  No migrations to apply.
  Your models in app(s): 'rockets' have changes that are not yet reflected in a migration, and so won't be applied.
  Run 'manage.py makemigrations' to make new migrations, and then re-run 'manage.py migrate' to apply them.

This error message is saying that your data model does not match what’s currently in the database. When you deleted the migrations field, you deleted the instructions that said to change the launch_date field. However, your Django model itself still reflects this change.

To fix this, you need to go into your models.py file and manually reverse the change as well:

from django.db import models

# Create your models here.
class Rocket(models.Model):
    """A model of a rocket ship."""
    name = models.CharField(max_length=200)
    launch_date = models.DateField() # Update this line
    ready_to_launch = models.BooleanField(default=True)

Now, when you migrate the database, Django will confirm that the table schema and your model are in sync:

(django-tut) $ python3 manage.py migrate rockets
Operations to perform:
  Apply all migrations: rockets
Running migrations:
  No migrations to apply.

Looking good!

Deleting a model field

When you’re working with production-grade projects, you’ll likely not be the only developer on the team. That means other developers will be interacting with the database and making asynchronous changes.

Say that one of your teammates misunderstood the requirements and accidentally removed the launch_date field completely. (To replicate this behavior, go ahead and remove the launch_date field from your data model and apply the migration.) The truncated output of showmigrations shows what happened:

rockets
 [X] 0001_initial
 [X] 0002_remove_rocket_launch_date

Not a problem, right? Let’s try to revert the migration and see what happens:

(django-tut) $ python3 manage.py migrate rockets 0001_initial
Operations to perform:
  Target specific migration: 0001_initial, from rockets
Running migrations:
  Rendering model states... DONE
  Unapplying rockets.0002_remove_rocket_launch_date...Traceback (most recent call last):
  File "/django-migrations-tutorial/django-tut/lib/python3.8/site-packages/django/db/backends/utils.py", line 84, in _execute
    return self.cursor.execute(sql, params)
  File "/django-migrations-tutorial/django-tut/lib/python3.8/site-packages/django/db/backends/sqlite3/base.py", line 423, in execute
    return Database.Cursor.execute(self, query, params)
sqlite3.IntegrityError: NOT NULL constraint failed: new__rockets_rocket.launch_date
... # truncated for length

Uh-oh… Django won’t apply the migration because doing so would violate a constraint on the database.

Take a closer look at the table schema:

sqlite> .schema rockets_rocket
CREATE TABLE IF NOT EXISTS "rockets_rocket" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "launch_date" date NOT NULL, "name" varchar(200) NOT NULL, "ready_to_launch" bool NOT NULL);

You can see that the "launch_date" field has a constraint on it called NOT NULL. This means that each row in the database must have a value in this field — it cannot be empty. Django models carry this constraint by default.

Unfortunately, when your colleague removed the launch_date field, Django applied this change to the database, dropping that column from the table as well:

sqlite> select * from rockets_rocket;
1|Apollo|0
2|Orion|1

You cannot simply undo the change because you would be reverting to a database schema that requires the launch_date column to have a value in it. Yet, the table has existing rows that have no values for this field! Django is unable to reconcile the conflict, so the migration will not run.

To fix this, you’ll need to explicitly re-define the deleted table column in your data model:

from django.db import models

# Create your models here.
class Rocket(models.Model):
    """A model of a rocket ship."""
    name = models.CharField(max_length=200)
    launch_date = models.DateField() # Make sure this line exists
    ready_to_launch = models.BooleanField(default=True)

When you try to make the new migration, you should be greeted with the following prompt:

(django-tut) $ python3 manage.py makemigrations rockets
You are trying to add a non-nullable field 'launch_date' to rocket without a default; we can't do that (the database needs something to populate existing rows).
Please select a fix:
 1) Provide a one-off default now (will be set on all existing rows with a null value for this column)
 2) Quit, and let me add a default in models.py
Select an option:

This time, Django can ask you explicitly what you want to do about the non-nullable field launch_date. Select the option to provide a one-off default value:

Select an option: 1
Please enter the default value now, as valid Python
The datetime and django.utils.timezone modules are available, so you can do e.g. timezone.now
Type 'exit' to exit this prompt
>>> timezone.now()
Migrations for 'rockets':
  rockets/migrations/0003_rocket_launch_date.py
    - Add field launch_date to rocket

The launch_date field accepts date objects, so you can use the timezone.now() function to provide the current date and time as a default value.

You can examine the newly created migrations file to confirm that Django will use that default value on existing rows in the database:

# rockets/migrations/0003_rocket_launch_date.py
class Migration(migrations.Migration):
    # ...
    operations = [
        migrations.AddField(
            model_name='rocket',
            name='launch_date',
            field=models.DateField(default=datetime.datetime(2021, 12, 2, 4, 9, 37, 82124, tzinfo=utc)),
            preserve_default=False,
        ),
    ]

Now, when you migrate the database, Django will add the launch_date back to the table, and populate the existing rows with the specified default value:

sqlite> select * from rockets_rocket;
1|Apollo|0|2021-12-02
2|Orion|1|2021-12-02

If you don’t want to supply a default value, then you can mitigate this issue by explicitly removing the NOT NULL constraint. This is done by passing an argument in to the field you’re defining in your data model:

from django.db import models

# Create your models here.
class Rocket(models.Model):
    """A model of a rocket ship."""
    name = models.CharField(max_length=200)
    launch_date = models.DateField(null=True) # Allow null values
    ready_to_launch = models.BooleanField(default=True)

Now, if the launch_date column is removed and added back in, Django will apply the migration even when existing table rows contain no value for this field.

Conclusion

Django’s object-relational mapper is a powerful tool and a boon to Python web developers across the world. In this tutorial, you’ve seen how you can work with Django migrations to quickly spin up database tables in Python without the need to write any SQL queries on your end.

You also learned a few techniques to troubleshoot errors like accidentally deleting a migration file or dropping a field from a database table. Working with data is a touchy endeavor, and while Django can help you reverse some mistakes, it can’t recover the data itself — so be sure to always back up your tables!

If you have any questions or comments, then please share them in the comments section below.

Thanks for reading!

Cut through the noise of traditional error reporting with LogRocket

LogRocket Dashboard Free Trial Banner

LogRocket is a digital experience analytics solution that shields you from the hundreds of false-positive errors alerts to just a few truly important items. LogRocket tells you the most impactful bugs and UX issues actually impacting users in your applications.

Then, use session replay with deep technical telemetry to see exactly what the user saw and what caused the problem, as if you were looking over their shoulder.

LogRocket automatically aggregates client side errors, JS exceptions, frontend performance metrics, and user interactions. Then LogRocket uses machine learning to tell you which problems are affecting the most users and provides the context you need to fix it.

Focus on the bugs that matter — try LogRocket today.

You ran makemigrations, then migrate and yet Django dares to throw an error? Incomparable betrayal! Let’s look through several cases.

Sidenote

For ages encountering migrations errors, I have been wipin the entire database and migrations files. Until one day an error occurred at a production server. There was no other option but to calm down and learn how to fix it.

🧸 Relation does not exist 1: not applied by you or Django

Run the command showmigrations and look at the output. If you see something like this:

firstapp
 [X] 0001_initial
 [X] 0002_auto_20190819_2019
 [X] 0003_auto_20190827_2311
 [ ] 0004_testunit

That means that the 0004 migrations was not applied, so just run migrate. If it stays misapplied or to avoid wasting time you can run this:

migrate firstapp 0004_testunit

If not, look further.

💔 Relation does not exist 2: You removed a migration’s file

Sidenote

The point of each migrations is to find the difference between the last version of the database structure and the current one. But Django does not look at the database itself, it compares your current models.py files with a virtual database made from migrations.py files. Then Django writes the changes down in new migrations files. And only with migrate you apply these changed to the database.

So if you remove something from migrations/ folder, the database will stay the same, but the Django’s idea of it won’t.

Case

So, you added a field type to a class Tag:

class Tag(models.Model)
   name = models.CharField(max_length=100)
   type = models.CharField(max_length=100)

You made a migrations, say, number 0002, it contains adding type field. Then you removed the migrations. After that, you made some changes, lived your best live, and decided to make migrations again.

Django will include creation of the type field to the migrations again. Therefore applying this migrations will give you an error:

ProgrammingError: column "tag_type" of relation "tag" already exists

How to Solve it 🧰

1. From migration file 0002_something.py remove the line about creating the type field.

from django.db import migrations, models


class Migration(migrations.Migration):

    dependencies = [
        ('firstapp', '0002_something'),
    ]

    operations = [
        ...
        # This .AddField below:
        migrations.AddField(
            model_name='tag',
            name='type',
            field=models.Charfield(max_length),
        ),
        ...
    ]

2. Migrate the 0002_something.py file:

migrate firstapp 0002_something

3. Make a new migration (it must only contain creating the type field):

makemigrations

4. Fake apply it like this:

 migrate firstapp 0003_something_two --fake

🔨 Relation does not exist 2: Renaming a field was not applied

This mysterious thing happened. I renamed type to type_name and I have a migrations that states it:

...    
    operations = [
        migrations.RenameField(
            model_name='tag',
            old_name='type',
            new_name='type_name',
        ),
    ]
...

And yet I get this error:

ProgrammingError at /test relation "firstapp_tag_type_name" does not exist

Possible culprit (myself and mass replace) a.k.a Sloppy Development installment

While changing names in the whole project automatically, I also unwillingly changed them in the migrations files. It is a great temptation to remove it all at once, but be careful. That may be the problem.

How to Solve it 🧰

Attempt #1: Order is wrong

The type field may have been altered before it was created because of the mass replace.

Try finding the whole life cycle of type field in your migrations – where it was added, where it was altered etc.

Attempt #2: Remove Migration file concerning the field

Remove every mention of the type field in migrations’ files (in operation). Then do whatever you want (rename it etc.) and make a migration again.

If the change is the only one in a migrations file, remove it all together.

You can remove the whole migration file, if it only contains type field manipulations. But be careful and alter dependencies for the following migration file (replace the deleted file’s name with the one before it).

Say, migrations’s files are 0002_something_before.py, 0003_something.py (removed) and 0004_brave_new.py.

So, after deleting 0003_something.py, in 0004_brave_new.py file:

dependencies = [
    ('firstapp', '0003_something'),
]

Replace 0003_something.py with0002_something_before:

dependencies = [
    ('firstapp', '0002_something_before'),
]

Otherwise you will get an error like this:

django.db.migrations.exceptions.NodeNotFoundError: Migration firstapp.0003_something_something dependencies reference nonexistent parent node 

Then, makemigrations and migrate.

Attempt #3: Remove every mention of the problematic field

If simply removing a migration and making another one doesn’t help…

Embrace yourself and remove every mention of type field. For my personal project, that inspired this post, it was quite time consuming.

However, as I see it now, you can’t just remove the field and make migrations of that, because type does not exist in the database. However, I can’t answer why.

You need to remove it from everywhere.

Then, makemigrations must show nothing, and the error won’t make am appearance.

🚫 Why you shouldn’t remove migrations

Summing up, Django does not care about database itself, except for when it returns errors. So Django’s idea of the database is made of migrations it have. That’s why when you run makemigrations, you get errors about migration files.

After applying new migrations, you will start getting all sorts of surprises: InvalidCursorName cursor does not exist or good old ProgrammingError: column does not exist and ProgrammingError: column of relation already exists.

Take my advice – don’t remove migrations because of migration errors, better learn how to work with them. Because in production you won’t be able to flush the database without a trouble (you kind of can, but you will need to insert missing data afterwards).

But if you did remove migrations…

Oh, been there.

I can say one thing – you will need to keep reversing changes to the database until you don’t get any more errors. And then make this changes again the same way I showed you here. And while in most cases Attempt #3 works, some day it may fail you.

One day I will emulate this and come back and update this post with a quick solution, but now I am triggered enough by just the mention of it.

Transforming one field to another

You can transform pretty much everything with an exception.

Adding a through table to M2M relation (or backwards)

Usually you want to add a through table to store additional data about the relation, not remove it. Either way, Django won’t allow this transition.

Say, Django can remove all the additional data, but constraints like unique_together can ruin your architecture. So you need to do it manually.

Django is an incredible web framework that is actively developed and reflective of timely updates. Sometimes these updates break convention with past versions and some quirky behavior can arise. One such quirk is seen in the syntax used to install apps.

As of Django 3.2, the syntax for installing an application is appname.apps.AppnameConfig as opposed to previous versions where a simple appname would suffice. Let’s take a quick look at the difference. First, let’s define our project structure:

DjangoProject
  bestapp
    migrations
    __init__.py
    admin.py
    apps.py
    models.py
    tests.py
    views.py
  DjangoProject
    __init__.py
    asgi.py
    settings.py
    urls.py
    wsgi.py
  templates
  manage.py

Here we see boilerplate Django project structure with a single app having been installed via the manage.py startapp bestapp command. Among other files, this generates the bestapp/apps.py file with the following information:

from django.apps import AppConfig


class BestappConfig(AppConfig):
    default_auto_field = 'django.db.models.BigAutoField'
    name = 'bestapp'

Now we are ready to consider how to install this app into our Django project. As outlined in the documentation, for this version and previous versions as well, this is done by adding our app name via the DjangoProject/settings.py file in the following line:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    OUR APP GOES HERE
]

Old Syntax

In previous versions of Django apps were installed simply by adding their name into the INSTALLED_APPS list with very little specificity as to how those apps’ configuration was selected. This was done via the following syntax:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'bestapp'
]

The simple addition of 'bestapp' was enough to inform Django of our new app’s presence and inclusion in our project assets. This is no longer the syntax and will result in the following error:

django.core.exceptions.ImproperlyConfigured: Cannot import 'bestapp'. Check that 'bestapp.apps.CoreConfig.name' is correct.

New Syntax

As of Django 3.x the syntax for adding applications has changed. As outlined in the official documentation, the new syntax is as follows:

INSTALLED_APPS = [
    'bestapp.apps.BestappConfig',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

With this, running the migrate or makemigrations command will work as expected—unless of course there is some other error lurking.

Apps in Subdirectories

The new syntax also requires some updating the /apps.py file for any applications installed in subdirectory locations. Consider the following app install location:

.
└── DjangoProject/
    └── Apps/
        ├── bestapp/
        │   ├── migrations
        │   ├── __init__.py
        │   ├── admin.py
        │   ├── apps.py
        │   ├── models.py
        │   ├── tests.py
        │   └── views.py
        └── ...

In this project structure, it is now required to update the Apps/bestapp/apps.py file to reflect the following format:

from django.apps import AppConfig


class BestappConfig(AppConfig):
    default_auto_field = 'django.db.models.BigAutoField'
    name = 'Apps.bestapp'  # <------------- added 'Apps' (old version was name='bestapp')

Final Thoughts

This syntactic shift can cause a headache to be sure. For those used to the old syntax—the one that was used forever—it can take a while before realizing such a change has been made. This can cause hiccups when updating Django versions or in starting new projects using the latest version.

Понравилась статья? Поделить с друзьями:
  • Makefile ignore error
  • Makefile error exit
  • Make ошибка 127
  • Make verbose error
  • Mape ошибка прогноза