: email로 로그인 할 수 있도록 구현
# user/models.py
...
from django.contrib.auth.models import BaseUserManager, AbstractBaseUser
class UserManager(BaseUserManager):
def create_user(self, email, username, password=None):
if not username:
raise ValueError('Users must have an username')
user = self.model(
username=username,
email=email,
)
user.set_password(password)
user.save(using=self._db)
return user
# python manage.py createsuperuser 사용 시 해당 함수가 사용됨
def create_superuser(self, email, username, password=None):
user = self.create_user(
email=email,
username=username,
password=password,
)
user.is_admin = True
user.save(using=self._db)
return user
class User(AbstractBaseUser):
username = models.CharField("사용자 아이디", max_length=12, unique=True)
email = models.EmailField("이메일", max_length=100, unique=True)
password = models.CharField("비밀번호", max_length=128)
fullname = models.CharField('이름', max_length=20)
join_date = models.DateTimeField('생성시각', auto_now_add=True)
def __str__(self):
return f"{self.username}"
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['username']
objects = UserManager()
def has_perm(self, perm, obj=None):
return True
def has_module_perms(self, app_label):
return True
@property
def is_staff(self):
return self.is_admin
# trip/models.py
...
from place.models import Place as PlaceModel
from user.models import User as UserModel
class TripCourseType(models.Model):
typename = models.CharField("유형", max_length=100, unique=True)
def __str__(self):
return self.typename
class Trip(models.Model):
user = models.ForeignKey(UserModel, verbose_name="사용자", on_delete=models.CASCADE)
title = models.CharField("제목", max_length=100)
content = models.TextField("내용")
created_at = models.DateTimeField("작성일", auto_now_add=True)
start_at = models.DateTimeField("여행 시작일", null=True)
def __str__(self):
return f"{self.title} - {self.user.username}"
class TripCourse(models.Model):
trip = models.ForeignKey(Trip, verbose_name="여행일정", on_delete=models.CASCADE)
tripcoursetype = models.ForeignKey(TripCourseType, verbose_name="여행 코스 유형", on_delete=models.CASCADE)
place = models.ForeignKey(PlaceModel, verbose_name="여행 장소", on_delete=models.SET_NULL, null=True)
start_at = models.DateTimeField("시작 시간", null=False)
end_at = models.DateTimeField("종료 시간", null=False)
order = models.IntegerField("여행 코스 순서", null=False)
def __str__(self):
return f"{self.order} - {self.tripcoursetype} : {self.place.name}"
: API 구현을 위해 사용할 dummy data를 admin 페이지를 통해 생성
: BaseUserAdmin를 상속받아 admin 페이지에서도 User 생성 시 password가 해시될 수 있도록 함
# user/admin.py
...
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from .models import User
class UserAdmin(BaseUserAdmin):
list_display = ('id', 'username', 'fullname')
list_display_links = ('username', )
list_filter = ('username', )
search_fields = ('username', )
filter_horizontal = []
# 생성 / 수정 모두 readonly로 설정
readonly_fields = ('join_date', )
# 생성 시 write 가능, 수정 시 readonly field로 설정
def get_readonly_fields(self, request, obj=None):
if obj:
return ('username', 'join_date', )
else:
return ('join_date', )
def get_writeonly_fields(self, request, obj=None):
return ('password', )
fieldsets = (
("info", {'fields': ('username', 'fullname', 'password', 'join_date')}),
('permissions', {'fields': ('is_admin', 'is_active', )}),
)
admin.site.register(User, UserAdmin)
https://github.com/nbcamp-AI-2-fantastic4/MyLittelTrip_backend