티스토리 뷰

반응형

이제 본격적으로 DB를 구성하고 API를 만들기 위해서

ERD를 그려주겠습니다. 

아래 사이트를 이용할게요-!

 

http://aquerytool.com/

 

AQueryTool - AQuery.Web

{{source.erd_info.erd_name + '(' + source.erd_info.db_type + ')'}}

aquerytool.com

데모페이지에 들어가서 (aquerytool.com/?demo=y

예제를 보고 이것을 reference해서 ERD를 그려줄게요-!! (대학교 3학년때 했던건데,,,다 까먹,,,) 

 

 

aquerytool.com/help/index/ 여기 help에도 친절한 설명이 있습니다 (🥺)

 

[1] AQueryTool 을 써보자

 

우선 로그인을 해주시고

컨트롤 + 마우스 클릭 해서 

테이블만들기를 눌러줍니다. 

 

 

처음 테이블을 만들때는 ERD랑 데이터베이스 설정이 안되있으니까

물어보는 팝업이 뜨는데 대답해줍니다. 

(데이터베이스이름 뭐라 해줘야할지 몰라서 DB1 해줬습니다,,)

 

 

 

OK 해주면 이렇게 나옵니다.

 

 

 

이제 테이블추가를 하면 테이블이 바로 생기게 된답니다. 

Table은 attribute를 입력하게 되어있고 

 

- PK : Primary Key

- AI : Auto Increment

- FK: Foreign Key

- Null: Null값을 가질수있는지

 

attribute에 위에 해당되면 쳌쳌 해주면 됩니다. 

 

 

그리고 아래 그림처럼 ForeinKey 를 연결해주려면

 

이렇게 끌어와서 해주면 됩니다..!! 👍

 

 

 

 

[2] ERD 만들기 

 

이렇게 해줬습니다,, 

Question과 Family는 장고문서 보면  Many-to-many relationship인 것 같은데

딱 질문만 담겨있는 DB를 따로 만들고 싶기도 했고 

이 툴에 다대다 관계 설정 하는 법이 없는 것 같아서 중간? 연결? DB인 FamilyQuestion을 따로 만들었어요 

 

 

[3] 모델만들기 

위에서 만든 ERD를 기반으로 장고의 Model field reference 문서를 참고해서 모델을 만듭니다 :-)

 

그 전에 알아야할 것 두가지가 있는데요,,,!! 

첫번째, 기본적으로 장고 모델에  id 필드(auto increment primary key) 가 자동으로 만들어지므로 id필드는 따로 만들지 않아도 됩니다. 

 

 

두번째,  ERD 그릴때, foreignKey를 id로 해줬지만

장고모델 에서는 id가 아니라 인스턴스를 가지게 해줍니다.

예를 들어 아래 예제와 같이 reporter_id가 아니라 reporter 이렇게 인스턴스를 가지게 해줍니다. 

 

그럼 models.py에 가서 모델을 만들어보겠습니다. 

1) Question 

class Question(models.Model):
    title = models.TextField()

 

2) Family

class Family(models.Model):
    join_date = models.DateTimeField()

 

3) User 

class User(models.Model):
    family = models.ForeignKey('Family', on_delete=models.SET_NULL, null=True)
    nickname = models.TextField()

 

장고의 ForeignKey에는  on_delete option이 있습니다.

ForeignKey로 reference하고 있는 object가 삭제될때 어떻게 할것이냐!!! 를 지정해주는 옵션이에요 

 

문서 설명을 캡쳐하기 너무 내용이 길어서 여기서 캡쳐해왔습니다. 

 

https://www.it-swarm.dev/ko/python/장고-모델에서-ondelete는-무엇을-하는가/825589735/

 

저는 SET_NULL 해줬어요-!! 

Family가 지워지면 User의 family가 null이 되도록..!! 

 

그리고 SET_NULL 하려면 이 필드가 nullable하다라는 설정도 해줘야해서 null=True도 넣었습니다. 

 

 

4) FamilyQuestion

class FamilyQuestion(models.Model):
    question = models.ForeignKey('Question', on_delete=models.CASCADE)
    family = models.ForeignKey('Family', on_delete=models.CASCADE)
    create_date = models.DateTimeField()

 

FamilyQuestion(가족에게 보낸 질문)은 Question이나 Family가 지워지면 같이 삭제되도록 해주려고 on_delete 옵션을 CASCADE 넣어줬어요-!

 

5) Answer

class Answer(models.Model):
    family_question = models.ForeignKey('FamilyQuestion', on_delete=models.CASCADE)
    user = models.ForeignKey('User', on_delete=models.CASCADE)
    title = models.TextField()
    create_date = models.DateTimeField()

 

Answer도 질문이나 답변의 주인이 삭제되면 같이 삭제되도록 on_delete 옵션으로 CASCADE 넣어줬어요-!

 

 

 

최종코드는 아래와 같습니다. 

 

 

 

 

 

[4] 모델 변경사항 마이그레이션 

 

 

(참고로 Question모델은 이전에 추가한 것이라서 여기 안나왔어요)

 

 

 

 

 

[5.1] ForeignKey 옵션 테스트해보기  - 쉘에서 

 

1) 쉘 실행

 

아래 명령어로 쉘에 들어가주세요 

python manage.py shell

 

2) 모델, 타임존 import 하기

 

question 앱으로 부터 models 파일을 import 해주세요 

from question import models

 

이러면 이제 모델에 접근할때 models 프리픽스 붙여서 models.Question~~ 이렇게 접근해야하는데,

만약 models. 붙이기 귀찮다!!! 하면 

 

이렇게 import 해주세요-!! (저는 이렇게 해줄게요)

from question.models import Question, Family, User, FamilyQuestion, Answer

 

그 다음에 timezone을 import 해주세요-!! 

from django.utils import timezone

 

settings.py에서 Time_zone을 아래와 같이 지정해줬는데요, 

 

 

 

 timezone.now() 말고 timezone.localtime() 해야지 settings.py에서 지정해준 Time_zone 형식으로 나오더라구요..!

 

 

그래서 모델만들때 now말고 localtime을 써줍니다. 

 

 

3) ForeignKey 옵션 테스트

 

아까 ondelete=~~ 해서 foreignKey 옵션 지정해준 것을 테스트해보겠습니다!+!

User가 참조하고 있는 Family가 지워질때 family가 null로 지정되는지 테스트 해볼게요-!

 

 

family 하나를 만들고 

family = Family(join_date=timezone.localtime())

 

DB에 저장해주세요

family.save()

 

id랑 join_date를 출력해보면 잘나오네요,,! (이전에 3개추가했어서 id가 4로 나온 것...!!) 

 

 

이렇게 DB에서 pk로 찾아봐도 잘 나옵니다..! 

family = Family.objects.get(pk=4)

 

그 다음 User를 만들어주세요 foreignkey로 family를 들고 있으니까  family를 넣어줍니다. 

user = User(family=family, nickname="첫째")

 

DB에 저장해줍니다. 

user.save()

 

전체 유저를 출력하면 

User.objects.all()

 

하나만 나옵니다..!! 

 

이제 이 유저가 참조하고 있는 Family를 지워볼게요-!! 

family.delete()

 

그리고 해당 유저를 가져와서 (출력 잘되니까 유저가 안지워진것 확인한 것-!!)

user = User.objects.get(pk=1)

 

family가 null인지 체크해보면!!!!! (파이썬에서 Null은 None으로 표현된다고 합니다.) 

user.family is None

 

true가 출력된 것을 볼 수 있습니다. 

 

 

[5.2]  ForeignKey 옵션 테스트 해보기 - 테스트 코드로!!

 

shell에서 하는 것 너무 불편해서 테스트 코드로 테스트 해주겠습니다. (참고: [Django] 튜토리얼 part 5 (1) - 테스트 작성하기 ) 

그리고 shell에서 하면 DB에 반영되니까 테스트 DB만 건들이도록 테스트에서 해주는게 맞아요,,,!!! 

 

Answer의 ForeignKey 옵션을 테스트 해볼게요-! 

 

 

tests.py에 들어가서 아래와 같이 테스트 코드를 작성해줍니다. 

 

 

 

그리고 테스트를 돌려주면...! (question은 저의 앱이름이에요)

python manage.py test question

 

성공이라고 나옵니다..!! 

 

 

 

[5.3] Relationships 테스트해보기 

 

장고의 문서에 가보면 

 

One-to-one relationships

 

Many-to-one relationships

 

Many-to-many relationships

 

여러 relationships를 확인해볼 수 있는 친절한 예제 코드를 제공하고 있습니다 👍

 

저는 테스트 하나만 작성해볼게요-!!

 

 

python manage.py test question

테스트 돌리면 성공이라고 나오네요-!! 

 

 

 

[추가]

그리고 ForeignKey 콤마 해도 되고 안해도 됩니다. 

(참고: docs.djangoproject.com/en/3.1/ref/models/fields/#django.db.models.ForeignKey)

 

 

콤마 함
콤마 안함.

 

 

Reference

victorydntmd.tistory.com/30

 

[DB] 관계형 DB에서의 관계 ( 1:1 / 1:M / N:M )

관계형 데이터베이스( MySQL, Oracle, MS-SQL, SQLite 등 )는 엔티티(객체)끼리 관계를 맺을 수 있어서 관계형 DB라는 이름이 붙었습니다. 관계는 두 엔티티가 서로 관련이 있을 때를 말하는데, 다음과 �

victorydntmd.tistory.com

 

velog.io/@rosewwross/Django-ERD

 

(Django) ERD~데이터베이스

스타벅스의 음료를 Mysql에 저장하는 과제를 wecode 백엔드 세션에서 다음의 과정을 거쳐서 같이 해보았다. 클로닝한 페이지: https://www.istarbucks.co.kr/menu/drink_list.do 설계 부분: 대분류(음료) > 소분류(

velog.io

 

반응형
댓글