TIL73. WetchaPedia Project : ERD 구성도 설계 & 모델 생성

ID짱재·2021년 11월 6일
0

WeChaCha Project

목록 보기
2/8
post-thumbnail

📌 이 포스팅에서는 WetchaPedia 클론 프로젝트 ERD 구성도 설계 과정과 Django Model 생성에 대해 정리하였습니다.



🌈 초기 세팅 & 모델 설계

🔥 Django 초기 세팅

🔥 데이터베이스 ORM 설계

🔥 Django Model 생성



1. 데이터베이스 ORM 설계

🤔 ORM 설계

✔️ User와 Movie 테이블이 메인 테이블이고, 이를 Many-To-Mnay로 연결할 여러 중계 테이블을 아래와 같이 설계했다.
✔️ Source는 이 영화 작품이 넷플릭스에서 상영인지, 왓챠에서 상영인지, 박스오피스 상영인지 구분하기 위해 만들었고, 둘다 상영되는 작품이 있기 때문에 이 또한 다대다로 설계했다.

🤔 ORM 설계 시 피드백 받은 내용

✔️ 사용자의 이름은 username 보다 name으로 필드명을 짓는 것이 적절하다. username은 ID를 별도로 사용할 때 필드명으로 사용한다.

✔️ DB의 필드명은 줄여서 사용하지 않는다. profile_img_url 보다 profile_image_url 처럼 명확하게 지어준다. runing_time 또한 minute인지 hour인지 명확하게 한다.

✔️ Many-To-Many 속성값을 사용하는 field는 ORM 설계할 때는 제외시킨다. Django에만 있기 때문에 models.py를 작성할 때 넣는다.

✔️ Many-To-Many 필드 사용의 장점은 Add로 값을 생성할 수 있고, related_name 값을 사용할 수 있고, 중계모델을 거치지 않고 바로 역참조를 가능하게 한다는 것이다.

✔️ ORM을 설계할 때, 다른 테이블의 id를 참조하는 필드는 언더바 id값(_id)을 필드명에 붙여준다.

✔️ Many-to-Many로 참조하는 필드명은 복수로 사용하고, ForeignKey로 참조하는 필드명은 단수를 사용한다. Many-to-Many 필드는 ERD 구성도에 넣지 않기 때문에 상관없지만, ForeignKey는 중계 테이블이 없기 때문에 ERD 구성도에 필드로써 명칭이 필요하다. 이에 grad_id로 필드를 생성해주었다.

🤔 soft delete & hard delete

✔️ soft delete는 회원이 탈퇴했을 때, 실제 해당 Object는 DB에서 삭제하지 않고 남기고, hard delete는 실제로 DB에서까지 지우는 것이다.

✔️ 특히, 회원정보 같은 경우 회사의 비지니스에 중요한 데이터이기 때문에 delete_at 필드를 만들어, 삭제 시점을 저장해 두고 이 필드값이 null인 사용자들만 실제 서비스를 사용가능하게끔 로직을 처리한다.

✔️ 즉, delete_at에 삭제 시점의 값이 존재하는 경우에는 사용자에게는 삭제된것 처럼 보이지만 실제 DB에는 데이터가 존재한다.

✔️ 이에 사용자 정보를 View에서 다룰 때도, null값을 가진 Object만 회원으로 서비스를 사용할 수 있게 처리해준다.

✔️ 또한 삭제되도 상관없는 Data일 경우는 DB에서도 바로 삭제될 수 있도록 하는 것이 hard delete이다.



2. Django Model 생성

🤔 앱 생성 & 앱 등록

✔️ 앱은 복수로 이름을 지어 아래와 같이 생성한다.

$ python manage.py startapp users
$ python manage.py startapp movies

✔️ settgins.py에 앱을 등록시킨다. 등록시키지 않으면 migration이 안된다.

🤔 users앱에 Model 생성하기

✔️ ERD 구성도를 바탕으로 users앱에 models.py를 작성한다.

✔️ 불필요한 주석은 제거해야한다.

✔️ email 필드는 로그인 시, ID처럼 사용되기 때문에 unique값을 True로 준다.

✔️ URL필드를 사용할 때는 길이를 2000이상 주어야 한다.

✔️ soft delete를 위해 deleted_at 넣을 때는 null=True값을 주어야 한다.

from django.db import models
class User(models.Model):
    name = models.CharField(max_length=50)
    password = models.CharField(max_length=200)
    email = models.EmailField(unique=True)
    profile_image_url = models.URLField(max_length=2000, null=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    deleted_at = models.DateTimeField(null=True)
    class Meta:
        db_table = "users"

🤔 movies앱에 Model 생성하기

✔️ ERD 구성도를 바탕으로 movies앱에 models.py를 작성한다.
✔️ ForeignKey 필드명은 단수, Many-to-Mnay 필드명은 복수를 사용한다.

from django.db import models
🚀 Movie Model
class Movie(models.Model):
    title = models.CharField(max_length=50)
    poster_image_url = models.URLField(max_length=2000)
    country = models.CharField(max_length=50)
    description = models.TextField()
    running_time_in_minute = models.IntegerField()
    released_at = models.DateField()
    grade = models.ForeignKey("Grade", on_delete=models.CASCADE)
    sources = models.ManyToManyField("Source", through="MovieSource", related_name="sources")
    genres = models.ManyToManyField("Genre", through="MovieGenre", related_name="genres")
    staffs = models.ManyToManyField("Staff", through="MovieStaff", related_name="staffs")
    ratings = models.ManyToManyField("users.User", through="Rating", related_name="ratings")
    wishlists = models.ManyToManyField("users.User", through="WishList", related_name="wishlists")
    comments = models.ManyToManyField("users.User", through="Comment", related_name="comments")
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    class Meta:
        db_table = "movies"
🚀 Movie Model
class Grade(models.Model):
    name = models.CharField(max_length=50)
    class Meta:
        db_table = "grades"
🚀 Source Model
class Source(models.Model):
    name = models.CharField(max_length=50)
    class Meta:
        db_table = "sources"
🚀 ModelSource Model
class MovieSource(models.Model):
    movie = models.ForeignKey("Movie", on_delete=models.CASCADE)
    source = models.ForeignKey("Source", on_delete=models.CASCADE)
    class Meta:
        db_table = "movie_sources"
🚀 Staff Model        
class Staff(models.Model):
    name = models.CharField(max_length=50)
    profile_image_url = models.URLField(max_length=2000)
    class Meta:
        db_table = "staffs"
🚀 MovieStaff Model                
class MovieStaff(models.Model):
    staff = models.ForeignKey("Staff", on_delete=models.CASCADE)
    movie = models.ForeignKey("Movie", on_delete=models.CASCADE)
    role = models.CharField(max_length=50, null=True)
    position = models.CharField(max_length=50)
    class Meta:
        db_table = "movie_staffs"
🚀 Rating Model        
class Rating(models.Model):
    user = models.ForeignKey("users.User", on_delete=models.CASCADE)
    movie = models.ForeignKey("Movie", on_delete=models.CASCADE)
    rate = models.DecimalField(max_digits=2, decimal_places=1)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    class Meta:
        db_table = "ratings"
🚀 WishList Model   
class WishList(models.Model):
    user = models.ForeignKey("users.User", on_delete=models.CASCADE)
    movie = models.ForeignKey("Movie", on_delete=models.CASCADE)
    created_at = models.DateTimeField(auto_now_add=True)
    class Meta:
        db_table = "wishlists"
🚀 Genre Model        
class Genre(models.Model):
    name = models.CharField(max_length=50)
    class Meta:
        db_table = "genres"
🚀 MovieGenre Model          
class MovieGenre(models.Model):
    movie = models.ForeignKey("Movie", on_delete=models.CASCADE)
    genre = models.ForeignKey("Genre", on_delete=models.CASCADE)
    class Meta:
        db_table = "movie_genres"
🚀 Comment Model                  
class Comment(models.Model):
    user = models.ForeignKey("users.User", on_delete=models.CASCADE)
    movie = models.ForeignKey("Movie", on_delete=models.CASCADE)
    description = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    class Meta:
        db_table = "comments"
🚀 LikeComment Model                          
class LikeComment(models.Model):
    comment = models.ForeignKey("Comment", on_delete=models.CASCADE)
    user = models.ForeignKey("users.User", on_delete=models.CASCADE)
    class Meta:
        db_table = "like_comments"
profile
Keep Going, Keep Coding!

0개의 댓글