User모델은 우리가 만들지 않아도 Django에서 자동으로 만들어 제공한다.
코드를 작성하지 않고 사용할 수 있는 User모델을 제공해줘서 너무 편하긴 하지만 현업에서는 Django에서 제공하는 User모델을 그대로 사용하는 경우는 없을 것이다.
제공해 주는 User모델에 필요한 항목이 없거나 불필요한 항목이 있을텐데 우리는 이 User모델을 커스텀하여 사용할 필요가 있다.
🧑🏻💻 그렇다면 어떻게 User모델을 커스텀 할 수 있을까?
📌 models.py
from django.db import models
from django.contrib.auth.models import AbstractUser
from django.contrib.auth.models import User
# Create your models here.
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)
# 방법 1 - AbstractUser 사용
class Users(AbstractUser):
pay_plan = models.ForeignKey(PayPlan, on_delete=models.DO_NOTHING)
# 방법 2 - AbstractUser 미사용
class UserDetail(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
pay_plan = models.ForeignKey(PayPlan, on_delete=models.DO_NOTHING)
PayPlan은 이전에 만들어 두었던 테이블(스키마)이다.
여기서 User모델에 PayPlan을 추가하여 User와 PayPlan간에 연관성을 형성하고 싶다.
위에서도 설명했 듯이 User모델은 Django가 자동으로 생성하여 제공해 주기 때문에 커스텀을 해야 PayPlan을 추가할 수 있다.
📌 AbstractUser 사용
이때 사용하는 객체가 바로 AbstractUser
이다.
class Users(AbstractUser):
pay_plan = models.ForeignKey(PayPlan, on_delete=models.DO_NOTHING)
이와 같이 Users라는 클래스가 AbstractUser
를 상속gkrp하여 그 안에 칼럼 'pay_plan'을 추가하면 현재 생성되어 있는(Django가 자동으로 제공한) Users모델에 'pay_plan'칼럼이 ForeignKey
로 추가되게 된다.
🔎 ForeignKey로 칼럼을 추가한 이유는 사용자의 결제 계획(Pay Plan)을 참조하여 사용할 수 있기 때문이다.
🔎 class [클래스 명](또 다른 클래스) 에서 '또 다른 클래스'부분이 해당 클래스가 다른 클래스를 상속받는 코드 작성 방법이다.
단 여기서 AbstractUser모델을 사용하는데 추가 설정이 필요하다.
settings.py
# Application definition
AUTH_USER_MODEL = "shortener.Users"
INSTALLED_APPS = [
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
# CUSTOM APP
"shortener",
]
위와 같이 인증
이 되는 모델이 shortener App에 있는 Users 테이블을 사용한다 라는 설정을 추가해 줘야한다.
📌 AbstractUser 미사용
class UserDetail(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
pay_plan = models.ForeignKey(PayPlan, on_delete=models.DO_NOTHING)
위의 방법은 생성된 Users모델에 칼럼을 추가하는 방법이다. 하지만 AbstractUser를 상속받지 않고 관리하는 방법도 있다.
바로 새로운 테이블(스키마)를 생성하여 이 테이블로 Users와 PayPlan사이의 연관성을 지어주는 것이다.
UserDetail
클래스 내에 user 칼럼에 User모델을, pay_plan 칼럼에 PayPlan모델을 생성하여 서로 연관성을 지어 줄 수 있다.
사용자의 정보에서 PayPlan 정보를 참조하고 싶을 때, UserDetail을 먼저 접근하여 'pay_plan'칼럼을 확인하면 ForeignKey로 칼럼이 생성되어 있기 때문에 결제 계획 정보를 확인 할 수 있다.
이제 위에서 models.py에 새로운 모델 Users와 UserDetail를 작성하였다. 이전에 PayPlan을 적용시킨 방법과 동일하게 마이그레이션 파일을 만들고 마이그레이션을 진행해보자.
python3 manage.py makemigrations
python3 manage.py migrate
🧨 Issue
여기서 makemigrations은 마이그레이션 파일이 생성이 되지만 migrate는 진행되지 않는다.auth-user 모델을 커스텀하기 위해선 Django가 User Model을 만들기 전(migrate 전)에 작업을 진행해야 하기 때문이다.
🧩 해결 방법
migrations
폴더에__init__.py
파일을 제외하고 모든 파일을 제거 및 dbsqlite 파일 제거 후 마이그레이션을 생성하여 migrate를 진행하자.
위의 이슈사항을 해결하고 나서 db.sqlite파일을 열어서 테이블(스키마)를 확인해 보면 아래와 같이 auto-user테이블이 아닌 [app_name]-users 모델이 생성이 된 것을 확인 할 수 있다.
이 모델을 기존에 auth-user가 가지고 있는 칼럼을 모두 가지고 있으며, Users모델에 작성한 pay_plan칼럼을 추가하여 가지고 있는 모습을 볼 수 있다.