[Django]인스타그램 클론코딩하기-모델링과 Django ORM

Cherry·2022년 1월 25일
0
post-thumbnail
post-custom-banner

인스타그램 모델링

인스타그램 erd

모델링erd

ERD 작성할때 mysql에서 테이블 칼럽을 조회하면 더 자세한 정보들을 알 수있어 참고하기 좋았다!
참고

Models

Base Model 작성하기

class BaseModel(models.Model):
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        abstract = True
  • 원래는 basemodel이 아니라 각자 모델들에서 created_at과 modified_at을 작성해줬지만 중복되는 코드들이 많아 이런식으로 모델을 만들어주고 나머지 모델들이 basemodel을 상속하면 코드가 더욱 간결하고 깔끔하게 만들어질 수 있다.
  • auto_now=True와 auto_now_add=True의 차이점
    • 수정일자 : auto_now=True 사용
      auto_now=True는 django model 이 save 될 때마다 현재날짜(date.today())로 갱신된다.(갱신 가능)
    • 생성일자 : auto_now_add=True 사용
      auto_now_add=True는 django model 이 최초 저장 시에만 현재날짜(date.today())를 적용한다.(갱신 불가능)

Profile Model 작성하기

class Profile(BaseModel):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    nickname = models.CharField(max_length=40, unique=True)
    introduction = models.TextField(null=True, blank=True)
    image = models.ImageField(upload_to="image")

    def __str__(self):
        return self.nickname
  1. Profile 모델은 User 모델과 1:1관계로 설정
  2. 사용자의 프로필 이미지는 ImageField()을 이용하여 지정
  3. null, blank 둘다 기본값이 False이나 introduction은 비어 있어도 되기 때문에 blank=True로 지정하여 필드가 폼(입력 양식)에서 빈 채로 저장되는 것을 허용, 폼에서 비워둘 수 있음. 데이터베이스에는 ' '이 저장됨.

Post Model 작성하기

class Post(BaseModel):
    author = models.ForeignKey(Profile, on_delete=models.CASCADE)
    title = models.CharField(max_length=100, null=True)
    content = models.TextField(null=True, blank=True)

    def __str__(self):
        return '{} : {}'.format(self.author, self.title)
  • null=True는 필드의 값이 NULL(정보 없음)로 저장되는 것을 허용, 결국 데이터베이스 열에 관한 설정
  • null=True 와 blank=True 를 모두 지정하면 어떤 조건으로든 값을 비워둘 수 있음을 의미
  • 단, BooleanField에 NULL을 입력할 수 있도록 하려면 null=True 를 설정하는 것이 아니라, NullBooleanField를 사용

File Model 작성하기

class File(BaseModel):
    post = models.ForeignKey(Post, on_delete=models.CASCADE)
    content = models.FileField(upload_to="file") #media/file/ 아래에 저장
  • 사진이나 영상을 업로드할때 FileField을 사용하였다
    • 먼저 settings에서 MEDIA_ROOT을 지정해줌으로서 해당 경로에 이미지나 영상이 저장된다.
    • 또한 upload_to 옵션을 사용하여 구체적인 디렉토리를 지정해 줄 수 있다.

Comment Model 작성하기

class Comment(BaseModel):
    post = models.ForeignKey(Post, on_delete=models.CASCADE)
    writer = models.ForeignKey(Profile, on_delete=models.CASCADE)
    content = models.TextField(blank=False)

    def __str__(self):
        return '{} commented {} post'.format(self.writer, self.post.title)
  • 포스트와 프로필 모델과 일대다 관계이다

Follow Model 작성하기

class Follow(BaseModel):
    follower = models.ForeignKey(Profile, on_delete=models.CASCADE, related_name='follower')
    following = models.ForeignKey(Profile, on_delete=models.CASCADE, related_name='following')

    def __str__(self):
        return '{} -> {}'.format(self.follower.nickname, self.following.nickname)
  • follower와 following 둘 다 foreignkey를 사용하여 프로필 모델과 일대다 관계이다. 이때 related_name을 명시하지 않으면 오류가 나기 때문에 항상 related_name을 적어주는 습관이 좋다.

    related_named은 역참조할때 사용된다. Follow객체를 정의할 때, follower와 following이라는 속성에 Profile 객체가 연결되어 정참조하고 있다. Profile 객체의 인스턴스와 연결되어 있는 Follow 객체를 거꾸로 불러올 때, follower와 following이라는 이름으로 부르기 위해 follower와 following이라는 속성에 related_names = 'follower', related_names = 'following'을 함께 지정해주었다. 나중에 역참조 할때 follower_set, following_set이런식으로 사용하면 된다!

Like Model 작성하기

class Like(BaseModel):
    post = models.ForeignKey(Post, on_delete=models.CASCADE)
    user = models.ForeignKey(Profile, on_delete=models.CASCADE)

    def __str__(self):
        return '{} liked {}'.format(self.user.nickname, self.post.title)

Migration

  • 모델의 변경 내역 히스토리를 관리해주는 파일
  • > python manage.py makemigrations <app-name> : <app-name>/model.py를 바탕으로 마이그레이션 파일 생성
  • > python manage.py migrate : model 변경 사항을 db에 업데이트 해주는 과정

Django ORM 적용해보기

DB tables

db

>>> from api.models import User, Profile, Post, Comment
>>> Profile.objects.create(user_id =2, nickname ='chaeri', introduction = 'heyyyyyyy')
<Profile: chaeri>
>>> User.objects.create(username='김초코',password='1111')
<User: 김초코>
>>> Profile.objects.create(user_id =3, nickname ='choco', introduction = '멍멍')
<Profile: choco>
>>> User.objects.create(username='세오스',password='2222')
<User: 세오스>
>>> Profile.objects.create(user_id =4, nickname ='ceos', introduction = '후후')
<Profile: ceos>
>>> Profile.objects.all()
<QuerySet [<Profile: chaeri>, <Profile: choco>, <Profile: ceos>]>

user

profile
확인해 보니 프로필도 유저도 잘생성된다:):)뿌듯하다!

>>> user1 = Profile.objects.get(nickname='chaeri')
>>> Post.objects.create(author=user1, title='first',content = '신기하다', like_num = 2)
<Post: first>
>>> Post.objects.create(author=user1, title='second',content = '모델링 어렵다....ㅠ', like_num = 4)
<Post: second>
>>> user2 = Profile.objects.get(nickname='choco')
>>> Post.objects.create(author=user2, title='배고파',content = '간식 줘', like_num = 5)
<Post: 배고파>

>>> Post.objects.filter(title='first') # 필터 함수 적용해보기
<QuerySet [<Post: first>]>

post

포스트도 잘생성되는것 같다!최고~~~

post-custom-banner

0개의 댓글