✏️

02-2 데이터를 관리하는 모델 본문

ETC./Do it! 점프 투 장고

02-2 데이터를 관리하는 모델

콩세 2022. 10. 12. 14:31

장고는 모델로 데이터를 관리한다.

보통 웹 개발에서는 데이터의 저장/조회를 위해 SQL 쿼리문을 이용한다. 이는 데이터 저장/조회를 위해서는

별도의 SQL 쿼리문을 배워야 한다는 말고 같다.

하지만 장고에서 모델을 사용하면 SQL 쿼리문을 몰라도 데이터를 저장/조회할 수 있다.


migrate와 테이블 알아보기

01단계 장고 개발 서버 구동 시 나오는 경고 메시지 살펴보기

 

명령프롬프트 or 터미널에서 py manage.py runserver 명령어를 입력하면 나오는 경고 메시지가 있다.

You have 18 unapplied migration(s). = 아직 적용되지 않은 18개의 migration이 있다.

위 오류를 해결하려면 py manage.py migrate를 실행해야 한다는 안내문도 있다.


02단계 config/settings.py 열어 기본으로 설치된 앱 확인하기

 

위 경고 메시지에 표시된 앱(admin, auth, contenttypes, sessions)은 어디에서 확인할 수 있을까아

config/settings.py 파일을 열어보면 어느정도 짐잘 할 수 있다고 한다 ..

config/settings.py 에서 INSTALLED_APPS 항목이다.

현재 장고 프로젝트에 설치된 앱 목록을 나타내며, 경고 메시지에 있었던 앱 이외에 messages, staticfiles앱도 있다.

두 앱은 데이터베이스와 상관 없으므로 경고 메시지에 언급되지 않은 것이다.


03단계 config/settings.py에서 데이터베이스 정보 살펴보기

 

config/settings.py 파일에는 설치된 앱뿐만 아니라 사용하는 데이터베이스에 대한 정보도 정의되어 있다.

DATABASES 설정 중 default의 'ENGINE' 항목을 보면 데이터베이스 엔진이 django.db.backends.sqlite3으로

정의되어 있음을 알 수 있다.

그리고 'NAME' 항목을 보면 데이터베이스는 BASE_DIR에 있는 db.sqlite3이라는 파일에 저장되어 있는 것도 알 수 있다.

 

- BASE_DIR은 프로젝트 디렉터리를 의미하며, 현재 우리의 BASE_DIR은 C:\projects\mysite이다.

- 데이터베이스를 여러 개 사용할 때 defualt에 지정한 데이터베이스 외에 추가로 등록해 사용할 수 있다.


04단계 migrate 명령으로 앱이 필요로 하는 테이블 생성하기

 

migrate 명령으르 실행하고 경고 메시지에 있던 앱들이 필요로 하는 테이블들을 생성하자.

명령 프롬프트/ 터미널 에서 py manage.py migrate를 입력했다.

migrate명령어 아래 메시지는 migrate를 통해 각 앱이 사용하는 테이블이 생성되었다는 뜻이다.

어떤 테이블이 생성되었는지 깊이 알 필요는 없음


05단계 DB Browser for SQLite로 테이블 살펴보기

 

migrate 명령어 입력 후 생성된 테이블이 궁금하다면..

SQLite의 GUI 도구(그래픽 도구)인 'DB Browser for SQLite'를 설치하면 데이터베이스의 테이블을 확인할 수 있다.

sqlitebrowser.org/dl에 접속해서 'DB Browser for SQLite'를 내려받자.

각 PC 환경에 맞는 설치 파일을 내려받아 설치하자. (나는 Standard installer for 64~설치했음)

뭐가 엄청 많아서 머리아플뻔 했는데 책에서 이 테이블 내용들 자세히 볼 필요 없다고 했다

장고는 테이블 작업을 위한 쿼리문을 알아서 수행하기 때문이라고 한다.


모델 만들기

파이보에서 사용할 모델을 만들어보자. 질문 답변 게시판을 만드는 것이 목표이기 때문에

질문과 답변에 해당하는 모델이 있어야 한다.

 

01단계 모델 속성 구상하기

 

- 질문 모델에서 필요한 속성

속성명 설명
subject 질문의 제목
content 질문의 내용
create_date 질문을 작성한 일시

 

- 답변 모델에서 필요한 속성

속성명 설명
question 질문(어떤 질문의 답변인지 알아야 하므로 질문 속성이 필요함)
content 답변의 내용
create_date 답변을 작성한 일시

02단계 pybo/models.py에 질문 모델 작성하기

 

질문 모델을 pybo/models.py에 작성하기.

질문 모델은 Question 클래스로 만든다. (클래스명=Question)

Question 모델에는 제목(subject), 내용(content), 작성일시(create_date)를 속성으로 추가했다.

subject는 최대 200자까지 입력할 수 있도록 max_length=200을 매개변수로 전달해서 설정함.

                 글자 수를 제한하고 싶은 데이터는 CharField 를 사용해야 한다.

content는 글자 수 제한이 없는 데이터이다.

                 글자 수 제한이 없는 데이터는 TextField를 사용한다.

create_date는 작성일. 날짜/시간 관련 속성은 DateTimeField를 사용한다.


03단계 pybo/models.py에 답변 모델 작성하기

질문 데이터와 같은 방법으로 답변 모델(Answer)도 작성했다.

 

Answer 모델은 어떤 질문에 대한 답변이므로 Question 모델을 속성으로 가져야 한다.

어떤 모델이 다른 모델을 속성으로 가지면 ForeignKey를 이용한다. (다른 모델과의 연결을 의미한다.)

on_delete=models.CASCADE는 답변에 연결된 질문이 삭제되면 답변도 함께 삭제하라는 의미이다.

 

▶on_delete가 뭔지 더 상세한 설명이 없어서 구글 찾아봤다.


04단계 config/settings.py를 열어 pybo 앱 등록하기

 

1~3단계에서 만든 모델을 이용하여 테이블을 생성하자.

테이블을 생성하려면, config/settings.py 파일에서 INSTALLED_APP 항목에서 pybo 앱을 추가해야 된다.

INSTALLED_APP에 추가한 pybo.apps.PyboConfig 클래스는 pybo/apps.py 파일에 있는 클래스이다.


05단계 pybo/apps.py 열어 살펴보기

 

이 파일은 pybo 앱으르 만들때 자동으로 생성된 것이다. 따로 생성할 필요 X.

 

- PyboConfig 클래스가 config/settings.py 파일의 INSTALLED_APPS 항목에 추가되지 않으면

  장고는 pybo 앱을 인식하지 못하고 데이터베이스 관련 작업을 할 수 없다.

= 장고는 모델을 이용하여 데이터베이스의 실체가 될 테이블을 만드는데, 모델은 앱에 종속되어 있으므로

  반드시 장고에 앱을 등록해야 테이블 작업을 진행할 수 있다.


06단계 migrate로 테이블 생성하기

 

속았다!

py manage.py migrate 명령어 입력했는데 제대로 안됨.

그 이유는 makemigrations 명령 먼저 실행해야 된다고....


07단계 makemigrations로 테이블 작업 파일 생성하기

 

모델이 생성되거나 변경된 경우 migrate 명령을 실행하려면 테이블 작업 파일이 필요하고,

테이블 작업 파일을 만들려면 makemigrations 명령을 실행해야 된다.

migrate 전에 makemigrations 먼저 실행하자.


08단계 makemigrations로 생성된 파일 위치 살펴보기

 

 

makemigrations 명령을 수행하면 pybo/migrations/0001_initial.py 라는 파일이 자동으로 생성된다.

 


09단계 makemigrations 한 번 더 실행해 보기

 

No changes detected : 

모델의 변경사항이 없다면 '모델 변경 사항 없음'이라고 알려 주는 것이다.


10단계 migrate 실행하기

 

 migrate 명령어 실행하기

py manage.py migrate 명령어를 실행하면 장고는 등록된 앱에 있는 모델을 참조하여 실제 테이블을 생성한다.


11단계 DB Browser for SQLite로 생성된 테이블 확인하기

 

 migrate 명령어 실행 후 테이블이 생성되었는지 DB Browser for SQLite에서 확인하기.

테이블명을 보면 Question 모델은 pybo_question으로, Answer 모델은 pybo_answer로 테이블명이 지어졌다.


데이터 만들고 저장하고 조회하기

 

01단계 장고 셸 실행하기

 

장고 셸을 실행해 보면 파이썬 셸과 비슷한 것 같다는 생각이 들 수 있다.

하지만 장고 셸은 장고에 필요한 환경들이 자동으로 설정되어 실행되므로 파이썬 셸과는 차이가 있다.

py manage.py shell 명령어 실행


02단계 Question, Answer 모델 임포트하기

 

from pybo.models import Question, Answer 입력

=> Queston과 Answer 모델을 장고 셸에 임포트.


03단계 Question 모델로 Question 모델 데이터 만들기

 

q = Question(subject='pybo가 무엇인가요?', content='pybo에 대해서 알고 싶습니다.', create_date=timezone.now())

 

Question 모델을 이용해서 Question 모델 데이터 하나 만들기.

Question 모델의 subject 속성에 제목, content 속성에 문자열로 질문내용 입력,

                           create_date 속성은 DateTimeField 이므로 timezone.now()로 현재 일시를 입력한다.

 


 

하.. 왜 NameError가 뜨는지 모르겠다

책에서 시키는 순서대로 입력하는건데 왜 나만 에러가 뜨는 것인가..

timezone이 뭐가 어떻다는 건데 ....

 

수정 1. 

pybo/models.py 파일에서

소괄호가 두군데 빠져 있었다.. 채웠음.

그런데도 계속 NameError가 뜬다. 도대체 이유가 뭘까..

 

수정 2.

pybo/migrations 폴더 지웠는데도 안된다.. 지우면 안되는 거였을까?ㅠ

 

수정 3.

그냥 다 갈아엎기로 했다

C: > projects > mysite 안에 config폴더랑 manage.py만 있는 상태로 돌아가서 (다른거 다 지움)

아예 처음부터 차근차근 다시 해봄

그런데 다시 해도 timezone이 정의되지 않았다고 뜬다ㅠ 주르륵

 

수정 4.

뭐가 잘못되었는지 드디어 발견했다.

내가 까막눈이었을까 아니면 책의 설명이 부족했던것일까..

책 본문에 이 코드를 쳐야됩니다 라고 적혀있는건 아닌데

아무 언급 없이 한 줄 추가되어 있었다고나 할까...ㅠ^ㅠ

q = Question(subject='pybo가 무엇인가요?', content='pybo에 대해서 알고 싶습니다.', create_date=timezone.now())

문제의 이 코드 전에 from django.utils import timezone 이걸 추가해야되는거였다고 한다.


from pybo.models import Question, Answer 입력

=> Queston과 Answer 모델을 장고 셸에 임포트.

 

from django.utils import timezone

=> timezone 임포트

 

q = Question(subject = 'pybo가 무엇인가요?', content='pybo에 대해서 알고 싶습니다.', create_date=timezone.now())

=> Question 모델의 속성값 부여.(객체 q 생성)

 

객체를 생성한 다음 q.save()를 입력하면 Question 모델 데이터 1건이 데이터베이스에 저장된다.


04단계 Question 모델 데이터의 id값 확인하기

 

Question 모델 데이터가 잘 생성되었는지 확인하기.

장고는 데이터 생성 시 데이터에 id값을 자동으로 넣어준다.

 

id는 데이터의 유일한 값이며, 프라이머리 키(PK: primary key)라고 부르기도 한다.

id값은 데이터를 생성할 때마다 1씩 증가한 값으로 자동으로 입력될 것이다.

 

q.id를 입력해서 id 값 확인.

 

 

 


05단계 Question 모델로 Question 모델 데이터 1개 더 만들기

3단계와 같은 방법으로 두번째 Question 모델 데이터 생성

(q=Question(... 입력하면서 실수로 마지막 소괄호 안닫고 엔터쳐서 3,4번째 줄처럼 됨. 나중에 수정하자 ㄱㅊ)


06단계 Question 모델로 데이터 모두 조회하기

 

지금까지의 과정은 모두 Question 모델 데이터를 저장하기 위한 것이었고, 이번에는 저장된 데이터를 조회해 보자.

Question.objects.all() : 저장된 모든 데이터를 조회하는 함수.

 

QuerySet 객체가 반환됨을 알 수 있다.

이 안에는 2개의 Question 객체가 포함되어 있다.

각 객체의 숫자 1,2 가 바로 장고에서 Question 모델 데이터에 자동으로 입력해준 id이다.


07단계 Question 모델 데이터 조회 결과에 속성값 보여주기

 

6단계에서 보여진 데이터는 한 눈에 알아보기 불편하므로

Question 모델에 __str__ 메서드를 추가한다.

이렇게 수정하면 데이터 조회 시 id가 아닌 제목을 표시해 준다.

(꼭 Question 아래에 적어야됨.(tap키 필수) 아무 생각 없이 Answer 아래 적었더니 실행 안되서 혼자 엄청 헤맸다.)


08단계 Question 모델 데이터 다시 조회해보기

 

7단계에서 모델을 수정했으니까 장고 셸(Terminal)을 다시 시작.

장고 셸에서 quit() 명령을 실행해서 종류 후 다시 시작한다.

Question 모델을 다시 임포트한 후 Question 모델 데이터를 조회하기.

전처럼 id가 조회되는 것이 아니라 제목이 표시된다.


09단계 조건으로 Question 모델 데이터 조회하기

 

7,8단계에서는 Question모델 데이터를 모두 조회했다.

조건을 주어 Question 모델 데이터를 추가하고 싶다면 filter 함수를 사용하면 된다.

filter 함수는 조건에 해당하는 데이터를 모두 찾아준다.

지금은 유일한 값인 id를 조건에 사용했으므로 Question 모델 데이터 하나만 나왔다.

하지만 filter 함수는 1개 이상의 데이터를 반환한다.

filter 함수는 반환값이 리스트 형태인 QuerySet이므로 딱 하나의 데이터만 조회하고 싶다면

get 함수를 쓰는 것이 좋다.


10단계 Question 모델 데이터 하나만 조회하기

 

get 함수는 filter처럼 리스트가 아닌 데이터 하나만 조회할 수 있다.

9단계에서 filter 함수를 사용했을때 보였던 []가 사라진 것을 확인할 수 있다.

두 함수의 차이점 꼭 알아두기.


11단계 get으로 조건에 맞지 않는 데이터 조회하기

 

get 함수를 이용해서 조건에 맞지 않는 데이터를 조회해봤다.

id = 3인 데이터는 존재하지 않기 때문에 오류가 발생했다.


12단계 filter로 조건에 맞지 않는 데이터 조회하기

 

filter 함수로도 id=3인 데이터를 조회해봤다.

filter 함수는 조건에 맞는 데이터가 없으면 빈 QuerySet을 반환한다.

get 함수는 반드시 1건의 데이터를 반환해야 한다는 특징이 있으므로 오류가 발생한 것이다.


13단계 제목의 일부를 이용하여 데이터 조회하기

 

subject에 "장고"라는 문자열이 포함된 데이터를 조회하려면 조건에 subject__contains를 이용하면 된다.

subject__contains='장고' => 'subject 속성에 '장고'라는 문자열이 포함되어 있는가?' 라는 뜻.

 


 

데이터 수정하기

 

01단계 Question 모델 데이터 수정하기

 

Question 모델 데이터를 수정하려면 우선 수정할 데이터를 조회해야 한다.

id = 2인 데이터를 조회.


02단계 subject 속성 수정하기

 

subject 속성을 수정하자.


03단계 수정한 Question 모델 데이터 데이터베이스에 저장하기

 

2단계만으로는 변경된 Question 모델 데이터가 데이터베이스에 적용되지 않는다.

반드시 save 함수를 실행해야 변경된 Question 모델 데이터가 데이터베이스에 반영된다.

 

⬇1~3단계

 


 

데이터 삭제하기

 

01단계 Question 모델 데이터 삭제하기

 

데이터 삭제는 수정과 비슷하다. id=1인 데이터를 삭제하자.

delete 함수를 수행하면 해당 데이터가 데이터베이스에서 즉시 삭제되며,

삭제된 데이터의 추가 정보가 반환된다. = (1, {'pybo.Question' : 1})

앞의 1은 삭제된 Question 모델 데이터의 id를 의미하고,

{'pybo.Question' : 1} 는 삭제된 모델 데이터의 개수를 의미한다.


02단계 삭제 확인하기

 

Question 모델 데이터가 삭제되었는지 확인하기.

첫 번째 질문은 삭제되고, 두 번째 질문만 남아있다.

 


 

연결된 데이터 알아보기

 

전에 Answer 모델을 만들 때 ForeignKey 로 Question 모델과 연결했었다.

Answer 모델은 Question 모델과 연결되어 있으므로 데이터를 만들 때 Question 모델 데이터가 필요하다

 

 

01단계 Answer 모델 데이터 만들기

 

id가 2인 Question 모델 데이터를 얻은 다음, 이를 이용하여 Answer 모델 데이터를 만들어보자.


02단계 id 확인하기

 

 

Answer 모델 데이터에도 id가 있다.

 


03단계 Answer 모델 데이터 조회하기

 

Answer 모델 데이터를 get 함수로 조회해 보자. 조건은 id를 사용한다.


04단계 Answer 모델 데이터 조회하기

 

Answer 모델 데이터에는 Question 모델 데이터가 연결되어 있으므로

Answer 모델 데이터에 연결된 Question 모델 데이터를 조회할 수 있다.

Answer 모델 객체인 a에는 question 속성이 있으므로 a를 통해 질문을 찾는 것은 매우 쉽다.

(답변을 통해 질문을 찾기가 쉽다는 뜻)


05단계 연결된 데이터로 조회하기: 질문을 통해 답변 찾기

 

answer_set을 사용해서 질문을 통해 답변 찾기 (4단계랑 반대)

Question 모델과 Answer 모델처럼 서로 연결되어 있으면 연결모델명_set과 같은 방법으로

연결된 데이터를 조회할 수 있다.

 

 

※ 주의!

- 하나의 질문 = 한 개 이상의 답변

   질문은 하나이지만 답변은 하나가 넘어갈 수 있다는 거.

 

- 그래서 답변으로 질문을 찾을 때는, 질문은 하나밖에 없기 때문에

   a.question 으로 실행할 수 있다.

 

- 반면 질문으로 답변을 찾을 때 답변은 여러개일 수 있기 때문에

   답변의 묶음을 조회하기 위해서 q.answer_set으로 조회한다.

   a.question에서는 _set을 붙일 수 없다.