프롤로그
일단 PoM서비스에서 내가 맡은 역할은 로그인/회원가입 기능이다. 그래서 프론트엔드와도 작업해야하니까, 일단 회원가입 할 때 모델링 부터 진행하겠다.
회원가입 모델링
일단
이렇게 각각 테이블을 생성해두고
ALTER TABLE individual ADD FOREIGN KEY (idx) REFERENCES user (idx)
ALTER TABLE enterprise ADD FOREIGN KEY (idx) REFERENCES user (idx)
로 기본키외래키 참조 연결해주면
위와 같이 연결이 된 것을 확인할 수 있다.
그냥 다이어그램만 작성한 것이지, 데이터베이스 MySQL이랑은 일단은 관계없다. 나중에 연결할때면 필요할 수도 있으나, 데이터베이스는 나도 이제 막 기초 배우기 시작한 데린이기에...
암튼 위의 다이어그램을 토대로 코드를 짜보자.
Models.py에다가
class User(AbstractBaseUser, PermissionsMixin):
idx = models.AutoField(primary_key=True, unique=True) #인덱스
email = models.EmailField(unique=True) #이메일, 아이디로 사용
name = models.CharField(max_length=50) #이름
phone = models.CharField(max_length=15) #핸드폰 번호
birthdate = models.DateField() #생년월일
addr = models.CharField(max_length=50) #주소
sex = models.CharField(max_length=1, choices=[('M', 'Male'), ('F', 'Female')]) #성별
user_type = models.CharField(max_length=10, choices=[('e', 'Enterprise'), ('i', 'Individual')]) #유저 등급
nickname = models.CharField(max_length=8, unique=True) #닉네임, 별명
password = models.CharField(max_length=100) # 비밀번호
def __str__(self):
return self.email # 필요에 따라 'self.name' 또는 'self.nickname'으로 변경 가능
class Enterprise(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
company_name = models.CharField(max_length=100) #회사명
department = models.CharField(max_length=100) #부서
position = models.CharField(max_length=100) #직책
def __str__(self):
return self.company_name
class Individual(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
school = models.CharField(max_length=100, null=True, blank=True) # 학교, 비어있어도 됨
department = models.CharField(max_length=100, null=True, blank=True) # 학과, 비어있어도 됨
def __str__(self):
return self.user.name
이렇게 코드를 짰다.
그리고 이제, 추가적으로 코드를 짰다.
.
class UserManager(BaseUserManager):
#새로운 사용자를 생성하고 데이터베이스에 저장하는 기능 수행
def create_user(self, email, password=None, **extra_fields): #이메일, 비밀번호, 그외 추가 필드 인자
if not email: #이메일이 제공되지 않으면 오류 처리
raise ValueError('The Email field must be set')
email = self.normalize_email(email) #이메일 정규화.
user = self.model(email=email, **extra_fields) #사용자 인스턴스 생성. UserManager 가 연결된 사용자 모델 참조
user.set_password(password) #사용자 비밀번호 설정
user.save(using=self._db) #비밀번호를 해시하여 저장, 평문 비밀번호가 데이터베이스에 직접 저장 X
return user
# 관리자 권한을 가진 사용자 생성하는 기능
def create_superuser(self, email, password=None, **extra_fields):
extra_fields.setdefault('is_staff', True)
extra_fields.setdefault('is_superuser', True)
# 필수 필드에 대한 기본값 설정
extra_fields.setdefault('birthdate', '1990-01-01')
extra_fields.setdefault('name', 'Admin')
extra_fields.setdefault('nickname', 'admin')
return self.create_user(email, password, **extra_fields)
사용자를 생성하고 데이터베이스에 저장하는 기능을 수행하는 UserManager 인데, BaseUserManager 을 상속받아서 작성하였다.
User 모델은 내가 만들고, 이것을 생성하고 데이터베이스에 넣기 위해서 한 번 필터링을 해준다 라고 생각하면 된다. email 을 도메인형식으로 바꿔주고 비밀번호도 한 번 변경해서 직접적으로 비밀번호가 데이터베이스에 저장하지 않게 해주는 그런 기능이다.
추가적으로 superuser 도 생성할 수 있는 함수도 준비되었다.
여기서 User부분을 살짝 수정을 하자
class User(AbstractBaseUser, PermissionsMixin):
idx = models.AutoField(primary_key=True, unique=True) #인덱스
email = models.EmailField(unique=True) #이메일, 아이디로 사용
name = models.CharField(max_length=50) #이름
phone = models.CharField(max_length=15) #핸드폰 번호
birthdate = models.DateField() #생년월일
addr = models.CharField(max_length=50) #주소
sex = models.CharField(max_length=1, choices=[('M', 'Male'), ('F', 'Female')]) #성별
user_type = models.CharField(max_length=10, choices=[('e', 'Enterprise'), ('i', 'Individual')]) #유저 등급
nickname = models.CharField(max_length=8, unique=True) #닉네임, 별명
password = models.CharField(max_length=100) # 비밀번호
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['name', 'nickname'] # createsuperuser 관리 명령 사용할 때 추가로 입력 요구하는 필드
objects = UserManager()
def __str__(self):
return self.email # 필요에 따라 'self.name' 또는 'self.nickname'으로 변경 가
USERNAME_FIELD = "email" 부분이 추가되었는데, 사용자명으로 사용하겠다 라는 의미이고
REQUIRED_FIELD는 createsuperuser명령을 사용할 떄 필요한 추가 필드이다. name과 nickname을 넣은 것이다.
AbstractBaseUser, BaseUserManager, PermissionsMixin
장고에서 사용자 모델을 커스터마이징 할 때 위 세개 클래스를 사용하여 고급 사용자 인증 시스템을 구현한다.
AbstractBaseUser
기본 사용자 모델의 추상 기반. 사용자 인증 시스템에서 필수적인 기본 필드와 메서드 포함. 사용자명, 이메일, 비밀번호등 사용자 인증에 필수적인 필드들을 자유롭게 정의하고 추가할 수 있다.
password, last_login필드와 is_activie 속성 등 최소한의 필드만 제공되고 나머지는 개발자가 정의
set_password(), check_password() 비밀번호 관리 메서드들이 구현되어 있어 안전하게 관리한다
BaseUserManager
사용자 생성과 사용자 관리 작업을 위한 메서드
PermissionMixin
권한 및 그룹 시스템과 관련된 필드와 메서드를 추가하는 믹스인 클래스
is_superuser, groups, user_permissions 필드가 추가되며, 사용자에게 권한을 부여하고 확인하는 메ㅓ들 제공
관리자 사이트에 접근할 수 있는지, 슈퍼유저인지 확인한다.
에필로그
일단 급해서 그냥 막 적었지만 코드는 위에서 변함 없을 것이다.
from django.db import models
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, PermissionsMixin
# Create your models here.
class UserManager(BaseUserManager):
#새로운 사용자를 생성하고 데이터베이스에 저장하는 기능 수행
def create_user(self, email, password=None, **extra_fields): #이메일, 비밀번호, 그외 추가 필드 인자
if not email: #이메일이 제공되지 않으면 오류 처리
raise ValueError('The Email field must be set')
email = self.normalize_email(email) #이메일 정규화.
user = self.model(email=email, **extra_fields) #사용자 인스턴스 생성. UserManager 가 연결된 사용자 모델 참조
user.set_password(password) #사용자 비밀번호 설정
user.save(using=self._db) #비밀번호를 해시하여 저장, 평문 비밀번호가 데이터베이스에 직접 저장 X
return user
# 관리자 권한을 가진 사용자 생성하는 기능
def create_superuser(self, email, password=None, **extra_fields):
extra_fields.setdefault('is_staff', True)
extra_fields.setdefault('is_superuser', True)
# 필수 필드에 대한 기본값 설정
extra_fields.setdefault('birthdate', '1990-01-01')
extra_fields.setdefault('name', 'Admin')
extra_fields.setdefault('nickname', 'admin')
return self.create_user(email, password, **extra_fields)
class User(AbstractBaseUser, PermissionsMixin):
idx = models.AutoField(primary_key=True, unique=True) #인덱스
email = models.EmailField(unique=True) #이메일, 아이디로 사용
name = models.CharField(max_length=50) #이름
phone = models.CharField(max_length=15) #핸드폰 번호
birthdate = models.DateField() #생년월일
addr = models.CharField(max_length=50) #주소
sex = models.CharField(max_length=1, choices=[('M', 'Male'), ('F', 'Female')]) #성별
user_type = models.CharField(max_length=10, choices=[('e', 'Enterprise'), ('i', 'Individual')]) #유저 등급
nickname = models.CharField(max_length=8, unique=True) #닉네임, 별명
password = models.CharField(max_length=100) # 비밀번호
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['name', 'nickname'] # createsuperuser 관리 명령 사용할 때 추가로 입력 요구하는 필드
is_staff = models.BooleanField(default=False)
objects = UserManager()
def __str__(self):
return self.email # 필요에 따라 'self.name' 또는 'self.nickname'으로 변경 가능
class Enterprise(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
company_name = models.CharField(max_length=100) #회사명
department = models.CharField(max_length=100) #부서
position = models.CharField(max_length=100) #직책
def __str__(self):
return self.company_name
class Individual(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
school = models.CharField(max_length=100, null=True, blank=True) # 학교, 비어있어도 됨
department = models.CharField(max_length=100, null=True, blank=True) # 학과, 비어있어도 됨
def __str__(self):
return self.user.name
전체코드는 이와 같고, 아마 나중에 Enterprise, Individual 에는 필요한 정보들을 더 넣으러 추가할 수도 있다.
이상이다.
'웹 개발' 카테고리의 다른 글
[장고] JWT 사용하기 #4 (0) | 2024.02.10 |
---|---|
[장고] 장고로 JWT 사용하기 #3 (1) | 2024.01.31 |
[장고] 회원가입 DRF이용하여 만들기 #2 (0) | 2024.01.30 |
[웹 개발] 개발환경과 서버환경 분리하기 (장고) (0) | 2023.12.24 |
[웹 개발] AWS Lightsail로 서버열기 (장고) (1) | 2023.12.24 |