본문으로 바로가기

사람은 실수를 한다.

역시 나는 오늘도 실수를 했다.

Django project에 있었던 user 폴더를 무심코 지워버렸다. 

Django Application이 총 6개인데 이 중 user을 지워버렸다.

쉽게 설명하자면, 내 웹서비스에서는 유저는 당연히 회원 가입 / 계정 정보 변경 / 계정 삭제 등 계정 관련 업무를 할 수 있어야 한다. 이 기능들을 담은 폴더를 삭제한 것이다. 

 

부랴부랴 다음 command line으로 users application 폴더를 재생성했다.

django-admin startapp users

그러나 서버를 돌려보았더니, 에러가 생겼다.

python manage.py runserver
------------------------------------------------------------------------------------------------------
Watching for file changes with StatReloader
Performing system checks...

System check identified no issues (0 silenced).
Exception in thread django-main-thread:
Traceback (most recent call last):
  File "/Users/noopy/.local/share/virtualenvs/django-airbnb-clone-AcLC9Tzu/lib/python3.8/site-packages/django/db/migrations/loader.py", line 166, in check_key
    return self.graph.root_nodes(key[0])[0]
IndexError: list index out of range

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/threading.py", line 932, in _bootstrap_inner
    self.run()
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/threading.py", line 870, in run
    self._target(*self._args, **self._kwargs)
  File "/Users/noopy/.local/share/virtualenvs/django-airbnb-clone-AcLC9Tzu/lib/python3.8/site-packages/django/utils/autoreload.py", line 54, in wrapper
    fn(*args, **kwargs)
  File "/Users/noopy/.local/share/virtualenvs/django-airbnb-clone-AcLC9Tzu/lib/python3.8/site-packages/django/core/management/commands/runserver.py", line 120, in inner_run
    self.check_migrations()
  File "/Users/noopy/.local/share/virtualenvs/django-airbnb-clone-AcLC9Tzu/lib/python3.8/site-packages/django/core/management/base.py", line 453, in check_migrations
    executor = MigrationExecutor(connections[DEFAULT_DB_ALIAS])
  File "/Users/noopy/.local/share/virtualenvs/django-airbnb-clone-AcLC9Tzu/lib/python3.8/site-packages/django/db/migrations/executor.py", line 18, in __init__
    self.loader = MigrationLoader(self.connection)
  File "/Users/noopy/.local/share/virtualenvs/django-airbnb-clone-AcLC9Tzu/lib/python3.8/site-packages/django/db/migrations/loader.py", line 49, in __init__
    self.build_graph()
  File "/Users/noopy/.local/share/virtualenvs/django-airbnb-clone-AcLC9Tzu/lib/python3.8/site-packages/django/db/migrations/loader.py", line 227, in build_graph
    self.add_external_dependencies(key, migration)
  File "/Users/noopy/.local/share/virtualenvs/django-airbnb-clone-AcLC9Tzu/lib/python3.8/site-packages/django/db/migrations/loader.py", line 191, in add_external_dependencies
    parent = self.check_key(parent, key[0])
  File "/Users/noopy/.local/share/virtualenvs/django-airbnb-clone-AcLC9Tzu/lib/python3.8/site-packages/django/db/migrations/loader.py", line 173, in check_key
    raise ValueError("Dependency on app with no migrations: %s" % key[0])
ValueError: Dependency on app with no migrations: users

 

users 폴더에서 데이터가 migration 이 안 됐다는 것이다.

Migrate이란, 다음과 같다:

  • SQL needs to learn how database look like.
  • You change the shape of data(=creating migration), and migrate to update database
  • Updating Database: Django shapes the data(or change the shape), you create migration, you apply migration

그럼 간단하다. user의 데이터가 아직 데이터베이스에 적용이 안 된 거라면, 데이터를 적용시키면 됐다. 여기까지는 순조로웠다.

python manage.py makemigrations           
--------------------------------------------------
Migrations for 'users':
  users/migrations/0001_initial.py
    - Create model User

하지만 여기서 에러가 터진다. InconsistentMigrationHistory 에러가 생긴다.

python manage.py migrate                 
-----------------------------------------------------------------------------
Traceback (most recent call last):
  File "manage.py", line 21, in <module>
    main()
  File "manage.py", line 17, in main
    execute_from_command_line(sys.argv)
  File "/Users/noopy/.local/share/virtualenvs/django-airbnb-clone-AcLC9Tzu/lib/python3.8/site-packages/django/core/management/__init__.py", line 381, in execute_from_command_line
    utility.execute()
  File "/Users/noopy/.local/share/virtualenvs/django-airbnb-clone-AcLC9Tzu/lib/python3.8/site-packages/django/core/management/__init__.py", line 375, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/Users/noopy/.local/share/virtualenvs/django-airbnb-clone-AcLC9Tzu/lib/python3.8/site-packages/django/core/management/base.py", line 323, in run_from_argv
    self.execute(*args, **cmd_options)
  File "/Users/noopy/.local/share/virtualenvs/django-airbnb-clone-AcLC9Tzu/lib/python3.8/site-packages/django/core/management/base.py", line 364, in execute
    output = self.handle(*args, **options)
  File "/Users/noopy/.local/share/virtualenvs/django-airbnb-clone-AcLC9Tzu/lib/python3.8/site-packages/django/core/management/base.py", line 83, in wrapped
    res = handle_func(*args, **kwargs)
  File "/Users/noopy/.local/share/virtualenvs/django-airbnb-clone-AcLC9Tzu/lib/python3.8/site-packages/django/core/management/commands/migrate.py", line 90, in handle
    executor.loader.check_consistent_history(connection)
  File "/Users/noopy/.local/share/virtualenvs/django-airbnb-clone-AcLC9Tzu/lib/python3.8/site-packages/django/db/migrations/loader.py", line 295, in check_consistent_history
    raise InconsistentMigrationHistory(
django.db.migrations.exceptions.InconsistentMigrationHistory: Migration admin.0001_initial is applied before its dependency users.0001_initial on database 'default'.

Inconsistent Migration History를 보고, "내가 users 폴더를 중간에 삭제하는 바람에 데이터를 업데이트 하는 게 꼬였구나!"를 깨달았다.

그래서 migration history를 조회했다.

python 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
contenttypes
 [X] 0001_initial
 [X] 0002_remove_content_type_name
sessions
 [X] 0001_initial
users
 [ ] 0001_initial

저기서 혼자서만 체크박스가 안 되어있는 놈(users 밑의 0001_initial)이 문제를 일으키는 게 분명했다. 

아직 각 application에 함수도 입력을 안 했으며, 개발 초창기에 생긴 문제이기 때문에, 극단적인 방법을 쓰기로 했다. 

혼자서만 체크박스가 안 되어서 문제라면, 모든 것들의 체크박스를 지워버리자!

 

Migrating from django user model to a custom user model

I am following these two references (one and two) to have a custom user model in order to authenticate via email and also to add an extra field to it. class User(AbstractBaseUser, PermissionsMixin...

stackoverflow.com

db.sqlite3에 migration 기록이 남아있을 것이다

따라서 프로젝트 폴더의 db.sqlite3 파일을 지워서, 아예 migration history 전체를 날려버리기로 했다. 그리고 나서 migration history를 찾아보니, 밑에처럼 체크박스들이 깔-끔해졌다. 

python manage.py showmigrations    
------------------------------------------------------
admin
 [ ] 0001_initial
 [ ] 0002_logentry_remove_auto_add
 [ ] 0003_logentry_add_action_flag_choices
auth
 [ ] 0001_initial
 [ ] 0002_alter_permission_name_max_length
 [ ] 0003_alter_user_email_max_length
 [ ] 0004_alter_user_username_opts
 [ ] 0005_alter_user_last_login_null
 [ ] 0006_require_contenttypes_0002
 [ ] 0007_alter_validators_add_error_messages
 [ ] 0008_alter_user_username_max_length
 [ ] 0009_alter_user_last_name_max_length
 [ ] 0010_alter_group_name_max_length
 [ ] 0011_update_proxy_permissions
contenttypes
 [ ] 0001_initial
 [ ] 0002_remove_content_type_name
sessions
 [ ] 0001_initial
users
 [ ] 0001_initial

그 이후에 일괄적으로 migration을 시키니, 정상작동했다. 

python manage.py migrate              
------------------------------------------------------------------------
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, sessions, users
Running migrations:
  Applying contenttypes.0001_initial... OK
  Applying contenttypes.0002_remove_content_type_name... OK
  Applying auth.0001_initial... 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 users.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 sessions.0001_initial... OK

물론 전에 입력한 유저 기록들은 지워졌지만, 개발 초기에 저지른 실수를 빠른 시간 내에 수습해서 만족스럽다.