“no such column” after adding a field to the model

前端 未结 7 1559
抹茶落季
抹茶落季 2020-12-28 08:53

environment DJANGO VERSION 1.9 Python 2.7.6

I added a field (scores) to a model class in models.py like this

from django.db import models
from django         


        
相关标签:
7条回答
  • 2020-12-28 09:14

    Easyes Solution: RENAME the field makemigrations migrate RENAME back makemigrations migrate

    0 讨论(0)
  • 2020-12-28 09:16

    Well the problem is NOT with your makemigrations command or models.py. It is because you have probably imported your class in the model (your database in this case) in on of your views.py files and the problem is with that. If you read the all of the error message then you can understand that easily.

    Just try commenting that importing part and run your python.manage.py makemigrations and python manage.py migrate commands then you can uncomment your import in your views.py file

    Hope this was useful for others as well

    0 讨论(0)
  • 2020-12-28 09:22

    Those migration issues bother me too when i have to update my app with new columns, so i've made a small bash with some python to search for troublesome columns, remove them, migrate, re-add them and migrate again.

    Here is the resolve.sh that calls python and migrations (has to be placed in the same folder as your manage.py file, like the .py files) :

    python manage.py shell < check.py
    
    read -p "Does it seem ok ? (y for ok/n for remigrate)" migrateok
    
    if [ $migrateok = "n" ]
    then
        python manage.py shell < rm_badcolumns.py
    
        python manage.py makemigrations
        sleep 1
        python manage.py migrate
    
        python manage.py shell < resume_badcolumns.py
    
        python manage.py makemigrations
        sleep 1
        python manage.py migrate
    
        echo It should work now..
    else
        echo No changes were made..
    fi
    

    check.py checks if there are issues with some models in the database :

    from <app>.models import *
    import os, sys
    from shutil import move
    from django.db import connection
    
    tables = connection.introspection.table_names()
    seen_models = connection.introspection.installed_models(tables)
    
    errorColumn = []
    is_fine = "EVERYTHING LOOKS FINE!"
    #looping through models to detect issues
    for model in seen_models:
        try:
            print(model.objects.all())
        except:
            is_fine = "WARNING SOME MODELS ARE CORRUPTED"
    
    print(is_fine)
    

    This check will tell the user if some models are not sync with your database.

    If the user chooses to "re-migrate", it calls rm_badcolumns.py :

    from <app>.models import *
    import os, sys
    from shutil import move
    from django.db import connection
    
    
    tables = connection.introspection.table_names()
    seen_models = connection.introspection.installed_models(tables)
    
    errorColumn = []
    
    for model in seen_models:
        try:
            model.objects.all()
        except:
            errorColumn.append(str(sys.exc_info()[1])[30::]+' =')
            #this weird expression just get the column that causes trouble
            #you may have to adapt indexes depending on error output in exc_info
    
    os.chdir('./<app>/')
    
    #removing columns from models.py based on the error pattern
    def replace(pattern, subst):
        with open('models_sub.py','w') as fout:
            with open('models.py','r') as models:
                for line in models:
                    fout.write(line.replace(pattern, subst))
    
        os.remove('models.py')
        move('models_sub.py','models.py')
    
    #applying this func to each error, and commenting out columns with an error mark to catch them back later
    for errorStr in errorColumn:
        replace(errorStr, '#error_mark '+errorStr)
    
    print 'Removing troublesome column for re-entering..'
    

    Then resolve.sh will start another migration. We uncomment the troublesome columns with resume_badcolumns.py to get them migrated again :

    from <app>.models import *
    import os, sys
    from shutil import move
    from django.db import connection
    
    
    os.chdir('./<app>/')
    
    #same search and replace func but returning True if sthg was replaced, and False otherwise
    def replace(pattern, subst):
        a = False
        with open('models_sub.py','w') as fout:
            with open('models.py','r') as models:
                for line in models:
                    fout.write(line.replace(pattern, subst))
                    if pattern in line:
                        a = True
        os.remove('models.py')
        move('models_sub.py','models.py')
    
        return a
    
    a = True
    #while error_marks are replaced, we go on looping
    while a:
        a = replace('#error_mark ', '')
    
    print 'Re-adding troublesome columns..'
    

    We make a final migration and everything should be fine.

    This is a kind of heavy and dirty artillery for a small problem but i wanted it to be automatized. A few points may need some rework, such as the way i identify which column is not synced, and i'd appreciate comments about this.

    0 讨论(0)
  • 2020-12-28 09:25

    Fast fix.

    First remove field scores, Then

    python manage.py makemigrations
    python manage.py migrate
    

    If any error happens

    python manage.py migrate --fake
    

    Then add field scores.Then

    python manage.py makemigrations
    python manage.py migrate
    

    Hope this helps.

    0 讨论(0)
  • 2020-12-28 09:36

    Keeping it short and precise, give that field a default value.

    For example:

    nickname = models.CharField(max_length=12, default=" ") 
    

    and not default=True

    If that doesn't work delete the migrations in your app's migration folder except

    __init__.py file and type both the commands again.
    python manage.py migrate
    python manage.py makemigrations appname
    python manage.py migrate(again)
    
    0 讨论(0)
  • 2020-12-28 09:38

    All, that u need: download «DB Browser for SQLite» and:

    1. Copy your ‘db.sqlite3’ to different Folder.
    2. Delete your ‘db.sqlite3’.
    3. Run ‘python3 manage.py make migrations’, then ‘python3 manage.py migrate’.
    4. Open your new ‘db.sqlite3’ in «DB Browser for SQLite» and find table ‘account_profile’
    5. Then do like 1st image. U should export ‘account-profile’ table to CSV file.
    6. Delete your new ‘db.sqlite3’ and return you old ‘db.sqlite3’
    7. Open your DB in «DB Browser for SQLite», then «File—>Import—>Tables from file CSV..» and choose ‘account_profile.csv’
    8. Then U will see, that in this table u should change columns ‘field1’ to ‘id’ and ‘field2’ to ‘user_id’. I did it on 2nd and 3rd images.
    9. Last, what should u do: Look at ‘id’ of your admin in the table ‘auth_user’ and change on this value in the ‘account_profile table’
    10. Delete your Admin-Model in DB(auth_user table)

    Yeah, 5-10 minutes to do it, but all is work)

    image1

    image2

    image3

    result

    0 讨论(0)
提交回复
热议问题