본문 바로가기

웹 개발

[프로젝트] 트러블 슈팅(관리자 페이지)

Django의 admin 페이지를 사용하려고 하던 중에 로그인이 안되는 문제가 발생했다.

이것과 관련된 내용으로 Django의 공식 문서를 찾아보니 is_staff 가 True여야 접속이 가능했다.

하지만 내가 설계한 프로젝트의 유저 모델은 is_staff 필드를 가지고 있지 않았다.

그래서 마이그레이션을 초기화하고 필드를 새롭게 추가하여 다시 마이그레이션을 만들었다.

class User(AbstractBaseUser):
    username = models.CharField(max_length=50, unique=True)
    name = models.CharField(max_length=20)
    is_superuser = models.BooleanField(default=False)
    is_staff = models.BooleanField(default=False)
    is_active = models.BooleanField(default=True)
    email = models.EmailField(max_length=254, unique=True)
    address = models.CharField(max_length=254)
    date_joined = models.DateTimeField(auto_now_add=True)

내가 설계한 유저 모델은 커스텀 매니저를 쓰고 있기 때문에 createsupueruser시

is_staff필드의 값을 True로 만들어주는 로직도 추가해야 했다.

def create_superuser(self, username, email, name, password, address=""):
        user = self.create_user(
            username=username,
            password=password,
            name=name,
            email=email,
            address=address,
        )
        user.is_superuser = True
        user.is_staff = True
        user.save()
        return user

이제 다시 접속을 해보는데 아직도 접속이 되지 않았다.

에러가 난 이유를 살펴보는데 비밀번호가 일치하지 않다는 이유였다.

프로젝트의 로그인 로직은 bcrypt의 checkpw를 사용하여 로그인 로직을 처리하고 있는데

Django의 admin의 로그인 로직은 Django의 check_password 메소드를 사용하고 있는 것 같았다.

그래서 이번엔 check_password 메소드를 오버라이딩해서 유저 모델에 기능을 추가하려고 했다.

class User(AbstractBaseUser):
    username = models.CharField(max_length=50, unique=True)
    name = models.CharField(max_length=20)
    is_superuser = models.BooleanField(default=False)
    is_staff = models.BooleanField(default=False)
    is_active = models.BooleanField(default=True)
    email = models.EmailField(max_length=254, unique=True)
    address = models.CharField(max_length=254)
    date_joined = models.DateTimeField(auto_now_add=True)

    # 고유 식별자로 사용되는 user모델의 필드 이름
    USERNAME_FIELD = "username"
    # 필수로 입력받고 싶은 값으로 createsuperuser시 사용
    REQUIRED_FIELDS = ["name", "email"]

    objects = CustomUserManager()

    def __str__(self):
        return self.username

    def soft_delete(self):
        self.is_active = False
        self.save()

    def check_password(self, raw_password):
        return bcrypt.checkpw(raw_password.encode('utf-8'), self.password.encode('utf-8'))

유저 모델에 check_password 메소드를 오버라이딩해서 내가 만든 해시 로직을 처리하도록 했다.

이 코드를 추가한 이후에 관리자 페이지에 정상적으로 로그인이 잘 되었다.

여기서 check_password를 오버라이딩한 함수를 만들었으니 로그인 로직도 오버라이딩한 check_password를 사용해서

불필요한 코드의 사용을 줄일 수 있겠다고 생각하였다.