카테고리 없음

Team project code review

김은수2 2023. 5. 14. 20:00

 

 

유저 앱


 

우리 팀에서는 로그인을 크게 두가지로 구분하였습니다.

 

첫번째 일반유저입니다, 여기서는 호텔의 손님이 됩니다.

두번째 관리자입니다. 이 호텔의 매니저 혹은 직원이며 추가와 삭제 권한이 있습니다. 

 

호텔서비스에서 손님계정으로 방의 수정/삭제가 가능하면 안되었기 때문에

일반 유저와 관리자를 구분해 주었습니다. 

 

def validate(self, data):
        if data['password'] != data['password2']:
            raise serializers.ValidationError("비밀번호와 비밀번호 확인이 일치하지않습니다!")
        return data

 

시리얼라이저에서 비밀번호 확인 코드를 만들었습니다.

흔히 사이트에서 볼 수 있는 비밀번호와 비밀번호 확인을 입력해서 일치하면 로그인 할 수 있는 구조입니다. 

일치하지 않거나 비밀번호가 없으면 

 

raise ValidationError("Passwords don't match")

위와 같은 에러가 일어납니다. 

 

    def create(self, validated_data):
        validated_data.pop('password2')
        user = super().create(validated_data)
        password = user.password
        user.set_password(password)
        user.save()
        return user

유저를 생성할 때 검증에 쓰인 password2는 지워줍니다. 

 

저희는 토큰 방식으로 로그인을 구현하였고 

토큰에 이메일, 유저네임, 어드민여부 등의 정보를 추가하였습니다.

 

class LoginSerializer(TokenObtainPairSerializer): 
    @classmethod
    def get_token(cls, user):
        token = super().get_token(user)
        token['email'] = user.email
        token['username'] = user.username
        token['is_admin'] = user.is_admin
        
        return token

 

또한 객실 등록에 있어 지점과 객실이름에 특수문자를 등록하지 못하게 유효성 검사를 하였는데 

 

def contains_special_character(name):
    name_regex = re.compile(r"^[a-zA-Z가-힣0-9\s]+$")
    if not name_regex.findall(name):
        raise ValidationError('이름에 특수문자를 사용할 수 없습니다!')
    return name

정규식을 이용하여 검사하고 틀리면 ValidationError 가 발생하게 하였습니다.

유저의 이름과 비밀번호에도 같은 방식으로 유효성검사를 했습니다.  

 

def check_username(username):
    username_regex = re.compile(r"[^ A-Za-z0-9가-힣+]")
    if username_regex.findall(username):
        raise ValidationError('이름에 특수문자와 초성을 사용할 수 없습니다!')
    return username


def check_password(password):
    password_regex = r"^(?=.*[A-Za-z])(?=.*\d)(?=.*[$@$!%*#?&^])[A-Za-z\d$@$!%*#?&^]{8,}$"
    if not re.match(password_regex, password):
        raise ValidationError('8자 이상의 영문 대/소문자, 숫자, 특수문자 조합이어야 합니다!')           
    return password

 

 

리뷰 앱 


class Review(models.Model):
    user = models.ForeignKey('users.User', on_delete=models.CASCADE)
    booked = models.ForeignKey(
        'hotels.Book', on_delete=models.CASCADE, related_name='booked_users')
    room = models.ForeignKey(
        'hotels.Rooms', on_delete=models.CASCADE, related_name='review_set')
    title = models.CharField(max_length=50)
    context = models.TextField(max_length=255)
    STAR_CHOICES = (
        (1, '1점'),
        (2, '2점'),
        (3, '3점'),
        (4, '4점'),
        (5, '5점'),
    )
    stars = models.PositiveIntegerField(choices=STAR_CHOICES, default=0)
    point = models.PositiveIntegerField(default=0)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    def __str__(self):
        return str(self.title)

리뷰 모델을 선언해 주었습니다. 

예약과 방 ,유저를 ForeignKey로 받고 별점과 포인트를 추가 했습니다. 

또한 extra_kwargs 변수를 사용하여 user, booked, room, point 필드들을 read_only로 설정하여, 해당 필드들이 업데이트되지 않도록 합니다.

 

호텔 앱


호텔 앱에서는  지점, 방, 예약기능의 CRUD를 관리합니다. 

 

지점은 저희 가상의 호텔이 5개의 지점을 가지고 있다고 가정하고 만들어졌습니다. 

대구, 양주, 고양, 세종, 포항의 5개 지점입니다. 

 

방은 해당 지점의 예약할 방입니다. 지점을 외래키로 가지며, 가격, 예약여부, 방인원 등의 정보들이 들어있습니다.

 

예약의 경우 방과 유저를 외래키로 받습니다. 예약일자를 판별하여 예약합니다. 

class Spots(models.Model):
    name = models.CharField(max_length=100, unique=True, validators=[
        contains_special_character])
    call_number = models.CharField(validators=[validate_phone_number], max_length=20, unique=True)

    location = models.CharField(max_length=200)
class Rooms(models.Model):
    all_status = [
        ('checkin', 'checkin'),
        ('empty', 'empty'),
    ]
    spot = models.ForeignKey(Spots, on_delete=models.CASCADE)
    name = models.CharField(max_length=100, validators=[
        contains_special_character])
    description = models.TextField(max_length=300, validators=[
        MinLengthValidator(10)], error_messages="10자 이상 입력하셔야합니다.")
    image = models.ImageField(null=True, blank=True)
    price = models.IntegerField(validators=[MinValueValidator(0)], null=False)
    max_members = models.IntegerField()
    status = models.CharField(choices=all_status, max_length=10)
class Book(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    room = models.ForeignKey(
        Rooms, on_delete=models.CASCADE, related_name='bookset')
    created_at = models.DateTimeField(auto_now_add=True)
    members = models.IntegerField(default=1)
    check_in = models.DateField() 
    check_out = models.DateField()

이렇게 3개의 모델을 가지고 있습니다

 

예약모델에서

        checkin_y_m_d = list(map(int, request.data["check_in"].split('-')))
        checkout_y_m_d = list(map(int, request.data["check_out"].split('-')))
        my_check_in = date(checkin_y_m_d[0], checkin_y_m_d[1],checkin_y_m_d[2])
        my_check_out = date(checkout_y_m_d[0],checkout_y_m_d[1],checkout_y_m_d[2])
        
        for i in all_checkins:
            print(f'{bool((my_check_in)>=(i.check_in))}')
            if my_check_in < i.check_in:  #체크인 날짜가 적절할 경우
                pass
                if my_check_out <= i.check_in:  # 체크 아웃 날짜가 적절한 경우
                    pass
                elif my_check_out > i.check_in:
                    return Response(f"예약 할 수 없음, 나의 예약 {my_check_in}~{my_check_out}, 이미 예약된 날짜 {i.check_in}~{i.check_out}")

            elif my_check_in >= i.check_in:  # 체크아웃 날짜가 적절하지 않을 경우
                if i.check_out <= my_check_in :
                    pass
                elif i.check_out > my_check_in:
                    return Response(f"예약 할 수 없음, 나의 예약 {my_check_in}~{my_check_out}, 이미 예약된 날짜 {i.check_in}~{i.check_out}")

.json 에서 받은 예약날짜 그러니까 체크인과 체크아웃 날짜를 datetime 객체로 변환하여 

비교하고 이것으로 예약가능 여부를 판별하는 코드입니다.