[Project] Threepark

[Capstone Design] 3. 백엔드 구현 - (4) DRF 개발 | DB & MODEL

mingyung 2024. 5. 21. 14:27

이제 DB Schema를 구성하고, django의 Model을 작성하자

 

DB Schema 구성

DB 스키마를 다음과 같이 구성한다.

계획의 과정에서 다음과 같은 형태로 구상했다. (이미지 자체는 결과 이미지다)

 

- 유저 정보의 경우 django에서 제공하는 모델을 사용하기로 함

 

모델이 많은 편이므로 user, follow, diary, music, image, emotion의 경우만 이야기 해 본다.

 

User

 

유저모델은 django의 auth모델을 사용할 것이다. 따라서 코드는 다음과 같이 작성한다.

from django.db import models
from django.contrib.auth.models import AbstractUser, BaseUserManager

class UserManager(BaseUserManager):
    def create_user(self, email, username, 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, username=username, **extra_fields)
        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_superuser(self, email, username, password=None, **extra_fields):
        extra_fields.setdefault('is_staff', True)
        extra_fields.setdefault('is_superuser', True)

        return self.create_user(email, username, password, **extra_fields)

class User(AbstractUser):
    REQUIRED_FIELDS = ['email'] 
    objects = UserManager()

    class Meta:
        db_table = 'user'
    
    def get_by_natural_key(self, username):
        return self.get(username=username)

 

 

Follow

follow모델의 경우 유저 두명과 두명의 관계가 정의된 status값이 들어간다.

 

이때 유저 두명은 유니크한 쌍이 되어야 한다. (유저간에 여러개의 관계가 있을 수 없다.)

from django.db import models

class Follow(models.Model):
    REQUESTED = 'requested'
    ACCEPTED = 'accepted'
    REJECTED = 'rejected'
    STATUS_CHOICES = (
        (REQUESTED, 'Requested'),
        (ACCEPTED, 'Accepted'),
        (REJECTED, 'Rejected'),
    )

    follower = models.ForeignKey(User, related_name='following', on_delete=models.CASCADE)
    following_user = models.ForeignKey(User, related_name='followers', on_delete=models.CASCADE)
    status = models.CharField(max_length=20, choices=STATUS_CHOICES, default=REQUESTED)

    class Meta:
        unique_together = ('follower', 'following_user')
        db_table = 'follow'
        managed = True

 

Music

음악 정보를 저장하는 Music의 경우 다음과 같이 작성한다.

from django.db import models

class Music(models.Model):
    music_title = models.CharField(max_length=100, null=True)
    artist = models.CharField(max_length=100, null=True)
    genre = models.CharField(max_length=20, null=True)
    
    class Meta:
        managed = True
        db_table = 'music'

 

Diary

음악 정보와 유저를 fk로 가지는 diary의 경우 다음과 같다.

타이틀과 내용(content), 최초 생성 시간과 마지막 업데이트 시간을 저장하고, 팔로워에게 공개여부를 정할 수 있게 한다.

class Diary(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    music = models.ForeignKey(Music, on_delete=models.SET_NULL, blank=True, null=True)
    
    title = models.CharField(max_length = 30)
    content = models.TextField(blank=True)
    registered_at = models.DateTimeField(auto_now_add=True)
    last_update_at = models.DateTimeField(auto_now=True)
    is_open = models.BooleanField(default=False)
    
    class Meta: 
        managed = True
        db_table = 'diary'

 

Image

일기를 fk로 가지고, 이미지의 url을 다루는 모델로, 다음과 같이 모델을 구성한다.

class Image(models.Model):
    diary = models.ForeignKey(Diary, on_delete=models.CASCADE)
    created_at = models.DateTimeField(auto_now_add=True)
    image_url = models.URLField(null=True)
    image_prompt = models.TextField(null=True)
    class Meta:
        managed = True
        db_table = 'image'

 

Emotion

일기를 fk로 가지고, emotion_label, chat을 다루는 모델

class Emotion(models.Model):
    diary = models.ForeignKey(Diary,on_delete=models.CASCADE)
    emotion_label = models.CharField(max_length=10, blank=True)
    emotion_prompt = models.TextField(blank=True)
    chat = models.TextField(blank=True)
    class Meta:
        db_table ='emotion'

 

 

migration

전체 모델을 저장하고, 다음을 순차 실행한다.

python manage.py makemigrations
python manage.py migrate