이슈-Django User 모델 확장(AbstractUser)

Gom La·2023년 4월 2일

이슈

목록 보기
1/3
post-thumbnail

🔖 ISSUE 다루기

ISSUE

Django 프로젝트의 User 모델을 확장하여 사용하고자 AbstractUser 모델을 상속받은 새 모델을 추가하여 마이그레이션을 생성하고 migrate를 진행, 아래와 같은 ValueError 발생

Traceback (most recent call last):
  File "/Users/cjy/Desktop/Source/Workspace/lagom_django/manage.py", line 22, in <module>
    main()
  File "/Users/cjy/Desktop/Source/Workspace/lagom_django/manage.py", line 18, in main
    execute_from_command_line(sys.argv)
  File "/Users/cjy/Desktop/Source/Workspace/lagom_django/venv/lib/python3.10/site-packages/django/core/management/__init__.py", line 446, in execute_from_command_line
    utility.execute()
  File "/Users/cjy/Desktop/Source/Workspace/lagom_django/venv/lib/python3.10/site-packages/django/core/management/__init__.py", line 440, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/Users/cjy/Desktop/Source/Workspace/lagom_django/venv/lib/python3.10/site-packages/django/core/management/base.py", line 402, in run_from_argv
    self.execute(*args, **cmd_options)
  File "/Users/cjy/Desktop/Source/Workspace/lagom_django/venv/lib/python3.10/site-packages/django/core/management/base.py", line 448, in execute
    output = self.handle(*args, **options)
  File "/Users/cjy/Desktop/Source/Workspace/lagom_django/venv/lib/python3.10/site-packages/django/core/management/base.py", line 96, in wrapped
    res = handle_func(*args, **kwargs)
  File "/Users/cjy/Desktop/Source/Workspace/lagom_django/venv/lib/python3.10/site-packages/django/core/management/commands/migrate.py", line 295, in handle
    pre_migrate_apps = pre_migrate_state.apps
  File "/Users/cjy/Desktop/Source/Workspace/lagom_django/venv/lib/python3.10/site-packages/django/utils/functional.py", line 57, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "/Users/cjy/Desktop/Source/Workspace/lagom_django/venv/lib/python3.10/site-packages/django/db/migrations/state.py", line 566, in apps
    return StateApps(self.real_apps, self.models)
  File "/Users/cjy/Desktop/Source/Workspace/lagom_django/venv/lib/python3.10/site-packages/django/db/migrations/state.py", line 637, in __init__
    raise ValueError("\n".join(error.msg for error in errors))
ValueError: The field admin.LogEntry.user was declared with a lazy reference to 'shortener.users', but app 'shortener' doesn't provide model 'users'.

➤ 과정

로그인회원가입만 구현하려는 목적에 기존에 Django기본으로 제공하는 User모델 을 사용하였고 어떤 커스텀도 필요하지 않았다.

Django 프로젝트의 User모델 을 이용하여 로그인회원가입을 구현하는 도중 User모델에 Forignkey를 갖는 필드가 필요해졌다.

📌 처음 설계와는 다르게 로그인한 사용자를 기반으로 결제 기능 을 추가하고자 User 모델을 확장하는 것으로 설계를 수정하였다.

class PayPlan(models.Model):
    name = models.CharField(max_length=20)
    price = models.IntegerField()
    updated_at = models.DateTimeField(auto_now=True)
    create_at = models.DateTimeField(auto_now_add=True)


class Users(AbstractUser):
    pay_plan = models.ForeignKey(PayPlan, on_delete=models.DO_NOTHING)

위의 코드와 같이 Users 모델이 AbstractUser 을 상속받게 한 후, 클레스 안에 'pay_plan'을 추가하여 Users 모델이 기존의 User 모델을 그대로 이용하며 새 필드만 가지는 모델로 사용할 수 있게 확장 코드를 작성하였다.

이렇게 코드 작성 후 DB 적용을 위해 마이그레이션을 진행하였지만 위와 같은 ValueError가 발생하였다.


➤ 원인

Django에서의 User 모델의 확장 방법 중 AbstractUserAbstractBaseUser 상속받아 확장하는 것은 중요한 조건이 필요했다.

그 조건은 Django가 첫 Users모델을 생성하기 전에 AbstractUser 또는 AbstractBaseUser 를 상속받는 모델이라 확정을 한 후 마이그레이션을 진행해야 한다는 것이다.

원인은 첫 마이그레이션을 진행하면 Django가 관여하고 관리하는 auth-user가 이미 생성이 되는데 그 이후에 생성된 User 모델을 변경하려고 충돌이 일어나기 때문이다.

물론 auth-user가 이미 생성이 된 후에도 변경이 가능하다지만 지금 수준에서는 다루기 어렵다고 판단하여 이런 상황이 나오지 않게 하려고 한다.


🧩 해결방법

  • 프로젝트 내 migrations폴더 안에 __init__.py폴더를 제외하고 모두 삭제한다.
  • db.sqlite 파일을 제거한다.
  • makemigrations로 마이그레이션 파일을 만든 후 migrate를 진행한다.

이 방법은 기존에 누적되어 있던 마이그레이션 파일을 최종 하나로만 마이그레이션 진행하는 방법이다.

그렇기 때문에 이 방법은 초기 개발 단계 또는 아직 운영하지 않은 단계 에서만 가능하다. 이미 운영중이거나 DB변경 내역이 중요한 단계에서는 할 수 없기 때문이다.

🫢 이미 DB에 필요한 데이터가 쌓여 있거나 DB 변경 내역이 필요하지 않다면 방법은 존재한다.

  • 위의 방법을 동일하게 진행하되 DB에서 살려야하는 데이터를 백업해 둔후 과감하게 진행하는 것이다.
  • 이후 동일하게 진행 후 백업해둔 DB를 새로 생성된 DB에 넣어주자.

User 모델의 확장하는 방법이 필요한 경우 아래를 참고하자.
cjyooong.log - Django User Model
Django 정식 Docs

profile
인생 개발자 라곰!!

0개의 댓글