과제 코드
User 모델 재정의
email 재정의 : unique 설정
username 재정의 unique 해제 (중복가능하게 변경)
profile_image 정의
USERNAME_FIELD와 REQUIRED_FIELDS는 Django의 사용자 모델에서 사용자 인증 및 데이터 관리 동작을 정의하기 위해 사용됩니다.from django.db import models from django.contrib.auth.models import AbstractUser class User(AbstractUser): email = models.EmailField('이메일', unique=True) username = models.CharField('닉네임', max_length=150) # unique=True 제거 profile_image = models.ImageField('프로필 이미지', upload_to='profile_images/', blank=True, null=True) USERNAME_FIELD = 'email' # 로그인 시 이메일 사용 REQUIRED_FIELDS = [] # email은 자동으로 필수 objects = CustomUserManager() def __str__(self): return self.email
1. USERNAME_FIELD
역할: Django의 인증 시스템에서 사용자 고유 식별자로 사용할 필드를 지정합니다.
기본적으로 Django는 username 필드를 사용자 고유 식별자로 사용합니다. 그러나 위 코드는 username 필드를 제거하고 대신 email 필드를 고유 식별자로 사용하도록 설정했습니다.
설정한 필드는 로그인, 인증, 사용자 검색 등의 작업에서 사용자 고유 식별자로 사용됩니다.
USERNAME_FIELD = 'email'
동작
사용자 인증 시 기본적으로 username 대신 email 필드를 요구합니다.
예를 들어, 로그인을 구현할 때 email 필드를 입력받아 인증하도록 동작합니다.
2. REQUIRED_FIELDS
역할: 사용자 생성 시 필수로 요구되는 추가 필드 목록을 지정합니다.
createsuperuser 명령을 통해 관리자 계정을 생성할 때 이 필드에 포함된 값들을 추가로 요구합니다.
예를 들어, REQUIRED_FIELDS = ['spouse_name']로 설정하면 관리자 계정을 생성할 때 spouse_name 필드 값을 입력해야 합니다.
REQUIRED_FIELDS = []
위 코드에서는 빈 리스트([])로 설정되어 있으므로, createsuperuser 명령 시 email 외에 추가 필드를 요구하지 않습니다.
USERNAME_FIELD에 설정된 필드는 자동으로 필수 필드가 되므로, REQUIRED_FIELDS에 다시 포함하지 않아도 됩니다.
3. objects = CustomUserManager()
Django의 기본 사용자 모델 관리자를 커스터마이징한 클래스입니다.
사용자 모델을 커스터마이징할 경우, 관련 매니저 클래스(CustomUserManager)를 정의하여 사용자 생성 메서드(create_user, create_superuser 등)를 수정하거나 추가 작업을 수행할 수 있습니다.
왜 CustomUserManager를 정의하는가?
사용자 모델 커스터마이징
Django의 기본 사용자 모델(AbstractUser)은 username을 고유 식별자로 사용합니다. 그러나 많은 시스템에서는 이메일을 고유 식별자로 사용하는 것이 더 유용합니다.
이를 위해 사용자 모델(CustomUser)을 재정의할 때, 사용자 계정을 생성하고 관리하는 방식도 수정해야 합니다.
따라서, BaseUserManager를 상속받아 이메일 기반 사용자 생성 로직을 구현하는 CustomUserManager를 정의합니다.
사용자 생성 로직의 일관성 보장
create_user: 일반 사용자 계정을 생성하는 표준 방법.
create_superuser: 관리자 계정을 생성하는 표준 방법.
이 두 메서드는 Django에서 필수적인 메서드이며, 이를 구현하지 않으면 사용자 모델이 제대로 동작하지 않습니다.
추가 작업 및 검증
예를 들어:
이메일을 정규화(normalize_email)하여 일관된 형식으로 저장.
필수 필드(is_staff, is_superuser) 값 검증.
추가적인 초기화 작업 수행.
즉, username이 아니라 email이 주 고유 식별자로 변환하기 위해 사용
Django에서 이메일로 사람을 구분하려면
Django가 원래 사용하던 username이라는 것을 없애고,
email이라는 것을 새로운 "이름"으로 사용해야 합니다.
사용자 정보를 관리하는 매니저(CustomUserManager)
여기까지는 우리가 "사람의 이름은 이메일이다!"라고 정한 것입니다.
하지만 컴퓨터는 이메일로 어떻게 새로운 사람을 만들지 모릅니다.
그래서 "매니저"라는 걸 만들어서 알려줘야 합니다.
이 매니저는 새 친구를 만드는 법과 특별한 친구(관리자)를 만드는 법을 가르칩니다.from django.contrib.auth.models import AbstractUser from django.db import models class CustomUser(AbstractUser): # 기본적으로 Django는 'username' 필드를 사용해서 사용자 구분을 함 # 하지만 우리의 모델에서는 username을 없애고 email을 대신 사용함 username = None # Django의 기본 username 필드를 제거함 # email 필드 추가 (고유 값으로 설정) # unique=True로 설정하면 데이터베이스에서 동일한 이메일이 저장되지 않도록 보장 email = models.EmailField(unique=True) # Django의 주 식별자를 설정하는 변수. 원래는 'username'이었음 # 여기서 'email'을 식별자로 설정 USERNAME_FIELD = 'email' # 관리자 생성 시 필수로 입력해야 하는 필드 # 기본적으로 'email'이 필수로 포함되기 때문에 비워둠 REQUIRED_FIELDS = [] # 사용자 모델에서 기본 동작을 관리할 매니저를 연결 # CustomUserManager를 통해 사용자 생성 로직을 커스터마이징 objects = CustomUserManager() # 이 사용자 객체를 문자열로 표현할 때 반환할 값 # 예: 사용자 목록을 출력할 때 이메일 주소가 표시됨 def __str__(self): return self.email
매니저 만들기from django.contrib.auth.models import BaseUserManager class CustomUserManager(BaseUserManager): """ 사용자 객체를 생성하고 관리하는 매니저 클래스 BaseUserManager를 상속받아 create_user와 create_superuser를 커스터마이징 """ def create_user(self, email, password=None, **extra_fields): """ 일반 사용자 생성을 위한 메서드 Parameters: - email: 사용자 이메일 (필수, 고유해야 함) - password: 비밀번호 (선택) - **extra_fields: 추가 필드 (예: 이름, 생년월일 등) Returns: - 생성된 사용자 객체 """ # 이메일이 없으면 사용자 생성이 불가능하므로 예외 발생 if not email: raise ValueError('이메일은 필수입니다.') # ValueError: 값이 잘못되었을 때 발생하는 표준 예외 # normalize_email: 이메일 주소를 깔끔하게 정리해주는 메서드 # 예: 대문자 → 소문자로 변환, 공백 제거 등 # 메서드 이름에서 'normalize_'를 사용하는 이유는 파이썬에서 메서드 이름에 _를 추가해 동작을 명확히 표현하는 관습 때문 email = self.normalize_email(email) # self.model은 현재 매니저가 연결된 사용자 모델(CustomUser)을 가리킴 # 사용자 객체 생성 (비밀번호나 추가 필드를 포함) user = self.model(email=email, **extra_fields) # 사용자 비밀번호 설정 # set_password: 비밀번호를 해싱(암호화)해서 저장 # 평문 비밀번호를 저장하지 않기 위해 반드시 해싱이 필요함 user.set_password(password) # save()를 호출해서 사용자 객체를 데이터베이스에 저장 # using=self._db는 다중 데이터베이스를 지원하는 경우 사용 user.save(using=self._db) return user # 생성된 사용자 객체 반환 def create_superuser(self, email, password=None, **extra_fields): """ 관리자를 생성하는 메서드 일반 사용자와의 차이는 is_staff와 is_superuser 필드를 True로 설정한다는 점 Parameters: - email: 관리자 이메일 - password: 관리자 비밀번호 - **extra_fields: 추가 필드 Returns: - 생성된 관리자 객체 """ # 관리자 필드 기본값 설정 extra_fields.setdefault('is_staff', True) # 관리자 권한에 필요한 필드 extra_fields.setdefault('is_superuser', True) # 최고 관리자 권한 # is_staff가 False이면 예외 발생 (관리자는 직원이어야 함) if not extra_fields.get('is_staff'): raise ValueError('관리자는 is_staff=True 이어야 합니다.') # is_superuser가 False이면 예외 발생 (관리자는 최고 권한을 가져야 함) if not extra_fields.get('is_superuser'): raise ValueError('관리자는 is_superuser=True 이어야 합니다.') # 일반 사용자 생성 메서드를 호출하여 관리자 생성 return self.create_user(email, password, **extra_fields)
매니저와 사용자 모델을 연결한다는 개념은 Django의 ORM(Object-Relational Mapping) 구조에서 매우 중요한 부분입니다. 이를 이해하려면 매니저가 무엇을 하는지, 모델에서 매니저가 왜 필요한지, 그리고 이 둘을 어떻게 연결하는지에 대해 깊이 알아야 합니다.
매니저란 무엇인가?
매니저는 Django 모델에서 데이터베이스에 접근하는 기본 인터페이스입니다. 즉, 매니저는 "어떻게 사용자(또는 데이터)를 생성하고 검색하고 관리할지"에 대한 로직을 담고 있습니다.
매니저의 역할
데이터베이스와의 모든 상호작용(예: 생성, 읽기, 수정, 삭제)을 처리합니다.
objects라는 이름으로 기본 제공되며, 우리가 직접 매니저를 만들면 이를 재정의할 수 있습니다.
매니저를 커스터마이징하면 사용자 정의 데이터 관리 로직(예: 사용자 생성 방법, 필터링 조건 등)을 추가할 수 있습니다.
매니저와 모델 연결을 쉽게 이해하기
이 부분을 **"친구를 만드는 방법"**으로 비유하면 다음과 같습니다:
매니저(CustomUserManager)는 친구를 만드는 방법을 알고 있습니다.
create_user → 일반 친구를 만드는 방법.
create_superuser → 특별한 친구(관리자)를 만드는 방법.
사용자 모델(CustomUser)은 이 매니저가 필요합니다.
사용자 모델(CustomUser)은 실제 데이터베이스에 저장될 사용자 정보를 담고 있습니다. 하지만, 이 사용자 데이터를 생성하거나 관리하는 구체적인 방법은 알지 못합니다.
그래서 사용자 모델에 매니저를 연결합니다.
사용자 모델의 objects 속성에 매니저(CustomUserManager)를 연결함으로써, "어떻게 친구를 만들고 관리할지"를 사용자 모델에게 알려줍니다.
매니저(CustomUserManager)는 사용자 데이터를 생성/관리하는 방법을 정의.
사용자 모델(CustomUser)은 매니저 없이 혼자 동작할 수 없으므로, objects 속성에 매니저를 연결.
매니저는 사용자 모델이 데이터베이스와 상호작용할 수 있도록 다리를 만들어줌.
여기까지....(아니아니.....개인과제 너무 많아요..)