본문 바로가기
개발자모드/혼자공부하는파이썬

[장고#05] SQLite 설치, 장고ORM기능, 모델생성, 테이블 생성/저장/조회/수정/삭제 (ft. 장고에 앱등록하기, 장고 쉘shell 실행하기)

by 요니L 2022. 8. 16.

 

 

보통 데이터 저장, 조회를 위해서는 별도의 SQL 쿼리문을 배워야 한다. 하지만 놀랍게도 모델을 사용하면 SQL 쿼리문을 몰라도 데이터를 저장, 조회할 수 있다. 모델이 무엇인지 알아보자~!

 

 


migrate와 테이블 알아보기

(1단계) 장고 개발 구동 시 나오는 경고 메시지 살펴보기 

모델을 알아보기 위해 python manage.py runserver명령 실행 시 나오는 경고 메시지를 보면, "중간쯤에 아직 적용되지 않은 18개의 migration이 있다(You have 18 unapplied migration(s))"고 한다.

D:\projects\mysite>python manage.py runserver
Watching for file changes with StatReloader
Performing system checks...

System check identified no issues (0 silenced).

You have 18 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
Run 'python manage.py migrate' to apply them.
August 10, 2022 - 11:36:35
Django version 3.1.3, using settings 'config.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CTRL-BREAK.

이 경고 메시지는 admin, auth, contenttypes, sessions 앱과 관련된 내용이며, 이 오류를 해결하려면 python manage.py migrate를 실행해야 한다는 안내를 확인할 수 있다. 

 

 

(2단계) config/setting.py 열어 기본으로 설치된 앱 확인하기

그러면 경고 메시지에 표시된 앱은 어디서 확인할 수 있고, 왜 경고 메시지가 언급되었는지는 config/setting.py 파일을 열어보면 어느 정도 짐작할 수 있다. 파일을 열어 INSTALLED_APPS 항목을 찾아보자.

(... 생략 ...)
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]
(... 생략 ...)

INSTALLED_APPS는 현재 장고 프로젝트에 설치된 앱이다. 경고 메시지에 언급되지 않은 message, staticfiles 앱도 보인다. 이 앱들은 데이터베이스와 상관없으므로 경고 메시지에 언급되지 않은 것이다. 

 

 

(3단계) config/setting.py 에서 데이터베이스 정보 살펴보기

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

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': BASE_DIR / 'db.sqlite3',
    }
}

 

DATABASES 설정 중 default'ENGINE' 항목을 보면 데이터베이스 엔진이 'django.db.backends.sqlite3'로 정의되어 있다. 그리고 'NAME' 항목을 보면 데이터베이스는 BASE_DIR에 있는 'db.sqlite3' 이라는 파일에 저장되는 것도 알 수 있다.

  

☞ BASE_DIR은 프로젝트 디렉터리를 의미한다. 현재 여기서의 BASE_DIR은 D:/projects/mysite 이다.

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

☞ SQLite는 파일 기반의 아주 작은 데이터베이스이다. (소규모 프로젝트에서 사용) 보통 초기 개발 단계에서 SQLite를 사용하여 빠르게 개발하고, 서비스로 제공할 때 운영환경에 어울리는 데이터베이스로 바꾼다. 

 

 

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

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

명령 프롬프트> python manage.py migrate 입력

(mysite) D:\projects\mysite>python manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying admin.0001_initial... OK
  Applying admin.0002_logentry_remove_auto_add... OK
  Applying admin.0003_logentry_add_action_flag_choices... OK
  Applying contenttypes.0002_remove_content_type_name... OK
  Applying auth.0002_alter_permission_name_max_length... OK
  Applying auth.0003_alter_user_email_max_length... OK
  Applying auth.0004_alter_user_username_opts... OK
  Applying auth.0005_alter_user_last_login_null... OK
  Applying auth.0006_require_contenttypes_0002... OK
  Applying auth.0007_alter_validators_add_error_messages... OK
  Applying auth.0008_alter_user_username_max_length... OK
  Applying auth.0009_alter_user_last_name_max_length... OK
  Applying auth.0010_alter_group_name_max_length... OK
  Applying auth.0011_update_proxy_permissions... OK
  Applying auth.0012_alter_user_first_name_max_length... OK
  Applying sessions.0001_initial... OK

(mysite) D:\projects\mysite>

migrate를 통해 admin, authom contenttypes, sessions앱이 사용하는 테이블이 생성된다. 

 

 

(5단계) DB Browser for SQLite로 테이블 살펴보기

migrate 명령을 통해 어떤 테이블이 만들어졌는지 확인해 보자. SQLite의 GUI 도구인 'DB Browser for SQLite'을 설치하면 테이블을 확인할 수 있다. 아래 경로로 접속하여 PC환경에 맞는 버전을 다운로드 하자.

 

https://sqlitebrowser.org/dl

 

Downloads - DB Browser for SQLite

(Please consider sponsoring us on Patreon 😄) Windows Our latest release (3.12.2) for Windows: Windows PortableApp Note - If for any reason the standard Windows release does not work (e.g. gives an error), try a nightly build (below). Nightly builds ofte

sqlitebrowser.org

 

 

 

(6단계) DB Browser for SQLite로 살펴보기

설치 후 실행한 다음 [데이터베이스 열기] ▶D:\projects\mysite\db.sqlite3 파일을 선택하면 앞에서 만든 테이블들을 눈으로 확인할 수 있다. 

 

 

장고에는 ORM(object relational mapping)이라는 기능이 있다. ORM은 파이썬으로 데이터 작업을 할 수 있게 해주는 기능이다. 즉, 장고에서는 쿼리문을 몰라도 파이썬을 안다면 데이터를 다룰 수 있다. ORM은 쿼리문을 자동으로 생성하므로 통일성이 보장되고 쿼리문 자체를 잘못 작성할 가능성도 없다. 또한 데이터베이스에 맞게 자동으로 쿼리문을 생성해 주므로 쿼리문 수정 작업이 사라진다. 이것이 ORM을 사용하는 이유이다.

 

 


모델 만들기

이제 파이보에서 사용할 모델을 만들어 보자. 파이보는 질문 답변 게시판이므로 질문과 답변에 해당하는 모델이어야 한다. 

 

(1단계) 모델 속성 구상하기

 

▷질문모델

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

▷답변모델

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

 

위 모델을 실제로 구현해 보자. 

 

 

(2단계) pybo/model.py에 질문 모델 작성하기

질문 모델Question 클래스로 만든다. 앞으로 대부분의 모델은 클래스로 만들 것이며, 이후 클래스명으로 모델을 언급할 것이다.

 

예) 질문 모델 = Question 모델

from django.db import models

# Create your models here.
class Question(models.Model):
    subject = models.CharField(max_length=200) #제목
    content = models.TextField()               #내용
    create_date = models.DateTimeField()       #작성일시

Question 모델에서는 subject , content, create_date를 속성으로 추가했다. 

-. subject : 최대 200자까지 입력할 수 있도록 max_length=200을 매개변수로 전달하여 설정하였고, 글자 수를 제한하고 싶은 데이터는 CharField를 사용해야 한다. 

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

-. create_date: 날짜, 시간과 관련된 속성은 DateTimeField를 사용한다. 

 

 

(3단계) pybo/model.py에 답변 모델 작성하기

답변 모델 = Answer 모델

class Answer(models.Model):
    question = models.ForeignKey(Question, on_delete=models.CASCADE)
    content = models.TextField()               #내용
    create_date = models.DateTimeField()       #작성일시

Answer 모델은 어떤 질문에 대한 답변이므로 Question 모델을 속성을 가져와야 해서 ForeignKey(FK)를 이용하였다. on_delete=models.CASCADE는 답변에 연결된 질문이 삭제되면 답변도 삭제하라는 의미이다. 

※ 장고 속성 공식 문서

https://docs.djangoproject.com/en/3.0/ref/models/fields/#field-types

 

Model field reference | Django documentation | Django

Django The web framework for perfectionists with deadlines. Overview Download Documentation News Community Code Issues About ♥ Donate

docs.djangoproject.com

 

☞ 모델에서 아래와 같은 에러가 난다면...

Unresolved reference 'django'

Unresolved reference 'models'

인터프리터 경로확인: C:\venvs\mysite\Scripts\python.exe로 설정되어 있어야 함. (각자의 경로 확인!)

 

 

(4단계) config/setting.py를 열어 pybo 앱 등록하기

1~3단계에서 만든 모델을 이용하여 테이블을 생성하자. 테이블 생성을 하려면 config/setting.py파일에서 INSTALLED_APPS 항목에 pybo앱을 추가해야 한다. INSTALLED_APPS 항목에 추가한 pybo.apps.PyboConfig 클래스는 pybo/apps.py 파일에 들어 있는 클래스이다. 잠깐 해당 파일을 확인하고 넘어가자. 

 

INSTALLED_APPS = [
    'pybo.apps.PyboConfig',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

 

 

(5단계) pybo/apps.py를 열어 살펴보기

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

from django.apps import AppConfig


class PyboConfig(AppConfig):
    name = 'pybo'

여기서 꼭 이해하고 넘어가야 할 점은 이 파일에 정의된 PyboConfig 클래스가 config/setting.py 파일의 INSTALLED_APPS 항목 추가되지 않으면 장고는 pybo앱을 인식하지 못하고, 데이터베이스 관련 작업도 할 수 없다. 다시 말해 장고는 모델을 이용하여 데이터베이스의 실체가 될 테이블을 만드는데, 모델은 앱에 종속되어 있으므로 반드시 장고에 앱을 등록해야 테이블 작업을 진행할 수 있다. 

 

 

(6단계) migrate로 테이블 생성하기

명령 프롬프트> python manage.py migrate

D:\projects\mysite>python manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
  No migrations to apply.
  Your models have changes that are not yet reflected in a migration, and so won't be applied.
  Run 'manage.py makemigrations' to make new migrations, and then re-run 'manage.py migrate' to apply them.

D:\projects\mysite>

그런데 migrate 명령이 제대로 수행되지 않는다. 왜냐하면 모델이 생성되거나 변경된 경우 migrate 명령을 실행하려면 테이블 작업 파일이 필요하고, 테이블 작업 파일을 만들려면 makemigrations 명령을 실행해야 하기 때문이다. 

파란색 부분은 'manage.py makemigrations 명령을 실행 후 manage.py migrate 명령을 실행하세요.' 라는 뜻이다.

 

 

(7단계) makemigrations로 테이블 작업 파일 생성하기

명령 프롬프트> python manage.py makemigrations

D:\projects\mysite>python manage.py makemigrations
Migrations for 'pybo':
  pybo\migrations\0001_initial.py
    - Create model Question
    - Create model Answer

makemigrations 명령은 장고가 테이블 작업을 수행하기 위한 파일들을 생성한다. 많은 장고 학습자가 makemigrations 명령을 실제 테이블 생성 명령으로 착각한다. 실제 테이블 생성 명령은 migrate이다.

 

 

(8단계) makemigrations로 생성된 파일 위치 살펴보기

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

 

 

(9단계) makemigrations 한번 더 실행해 보기

D:\projects\mysite>python manage.py makemigrations
No changes detected

makemigrations 명령을 한번 더 실행하면 'No changes detected' 라는 메시지가 뜬다. 모델의 변경사항이 없다면 '모델 변경 사항 없음'이라고 알려 주는 것이다.

 

 

(10단계) migrate 진짜로 실행하기

명령 프롬프트> python manage.py migrate

D:\projects\mysite>python manage.py makemigrations
Migrations for 'pybo':
  pybo\migrations\0001_initial.py
    - Create model Question
    - Create model Answer

D:\projects\mysite>python manage.py makemigrations
No changes detected

D:\projects\mysite>python manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, pybo, sessions
Running migrations:
  Applying pybo.0001_initial... OK

D:\projects\mysite>

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

 

 

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

▷ 데이터베이스 열기 경로 : D:\projects\mysite\db.sqlite3

실제 테이블명을 보면 Question 모델은 pybo_question으로, Answer 모델은 pybo_answer로 테이블 이름이 지어졌음을 확인할 수 있다. 

 

 

※ migrate 명령을 실행할 때 실제로 어떤 쿼리문이 실행될까?

명령 프롬프트> python manage.py sqlmigrate pybo 0001

D:\projects\mysite>python manage.py sqlmigrate pybo 0001
BEGIN;
--
-- Create model Question
--
CREATE TABLE "pybo_question" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "subject" varchar(200) NOT NULL, "content" text NOT NULL, "create_date" datetime NOT NULL);
--
-- Create model Answer
--
CREATE TABLE "pybo_answer" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "content" text NOT NULL, "create_date" datetime NOT NULL, "question_id" integer NOT NULL REFERENCES "pybo_question" ("id") DEFERRABLE INITIALLY DEFERRED);
CREATE INDEX "pybo_answer_question_id_e174c39f" ON "pybo_answer" ("question_id");
COMMIT;

D:\projects\mysite>

sqlmigrate를 실행하면 실제로 어떤 쿼리문이 실행되는지 볼 수 있다. 

 

 

 

 


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

지금까지 모델을 이용하여 실제 테이블을 만들었다. 그러면 장고에서는 모델을 어떻게 사용할까? 장고 셸을 사용하면 모델 사용법을 쉽게 익힐 수 있다. 

 

(1단계) 장고 셸 실행하기

명령 프롬프트> python manage.py shell

(mysite) D:\projects\mysite>python manage.py shell
Python 3.10.5 (tags/v3.10.5:f377153, Jun  6 2022, 16:14:13) [MSC v.1929 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>>

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

 

 

(2단계) Question, Answer 모델 임포트하기

>>> from pybo.models import Question, Answer

>>> from pybo.models import Question, Answer

장고 셸을 실행했으면 위 명령으로 Question과 Answer 모델을 장고 셸에 임포트하자. 

 

(3단계) Question 모델로 Question 모델 데이터 만들기

Question 모델의 subject 속성에 제목을, content 속성에 문자열로 질문 내용을 입력한다. create_date 속성은 DateTimeField이므로 timezone.now()로 현재일시를 입력한다. 

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

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

 

 

(4단계) Question 모델 데이터의 id값 확인하기

Question 모델 데이터가 잘 생성되었는지 확인해 보자. 장고는 데이터 생성 시 데이터 id 값을 자동으로 넣어준다. id는 데이터의 유일한 값이며, 프라이머리 키(PK)라고 부르기도 한다. id값은 데이터를 생성할 때마다 1씩 증가한 값으로 자동으로 입력된다. 

>>> q.id
1
>>>

 

 

(5단계) Question 모델로 Question 모델 데이터 1개 더 만들기

두 번째 Question 모델 데이터를 만들어 저장해 보면 id=2를 확인할 수 있다.

>>> q = Question(subject='장고 모델 질문입니다.', content='id 는 자동으로 생성되나요?', create_date=timezone.now())
>>> q.save()
>>> q.id
2
>>>

 

 

(6단계) Question 모델로 데이터 모두 조회하기

>>> Question.objects.all()

저장된 데이터를 조회해 보자. 장고에서 저장된 모델 데이터는 Question.objects를 사용하여 조회할 수 있다. 그리고 Question.objects.all()은 Question에 저장된 모든 데이터를 조회하는 함수이다.

>>> Question.objects.all()
<QuerySet [<Question: Question object (1)>, <Question: Question object (2)>]>
>>>

결과를 보면  QuerySet 객체가 반환됨을 알 수 있다. 그리고 QuerySet에는 2개의 Question 객체가 포함되어 있다.  여기서의 1, 2가 Question 모델 데이터에 자동으로 입력해준 id이다. 

 

 

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

6단계의 결과는 데이터 유형을 출력한 것이므로 사람이 보기 불편하다. 이때 Question 모델에 __str__ 메서드를 추가하면 된다. 그러면 데이터 조회 시 id가 아닌 제목을 표시해 준다.

from django.db import models


# Create your models here.
class Question(models.Model):
    subject = models.CharField(max_length=200)
    content = models.TextField()
    create_date = models.DateTimeField()

    def __str__(self):
        return self.subject

class Answer(models.Model):
    question = models.ForeignKey(Question, on_delete=models.CASCADE)
    content = models.TextField()
    create_date = models.DateTimeField()

 

(8단계) Question 모델 데이터 다시 조회해 보기

모델이 수정되었으므로 장고 셸을 다시 시작하자. 장고 셸에서 quit() 명령을 실행해 종료한 후 다시 장고 셸을 시작한다. 

>>> quit()

(mysite) D:\projects\mysite>python manage.py shell
Python 3.10.5 (tags/v3.10.5:f377153, Jun  6 2022, 16:14:13) [MSC v.1929 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from pybo.models import Question, Answer
>>> Question.objects.all()
<QuerySet [<Question: pybo가 무엇인가요?>, <Question: 장고 모델 질문입니다.>]>
>>>

그러면 Question 모델 데이터에 id가 아니라 제목이 표시된다. 여기서 '모델이 수정되었는데 왜 makemigrations, migrate 명령을 실행하지 않지?' 라는 의문이 들 수도 있는데 makemigrations, migrate 명령은 모델의 속성이 추가되거나 변경된 경우에 실행해야 하는 명령이다. 지금은 메서드가 추가된 것이므로 이 과정은 하지 않아도 된다. 

 

 

(9단계) 조건으로 Question 모델 데이터 조회하기

>>> Question.objects.filter(id=1)

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

>>> Question.objects.filter(id=1)
<QuerySet [<Question: pybo가 무엇인가요?>]>
>>>

filter 함수는 1개 이상의 데이터를 반환한다. 다만 filter 함수는 반환값이 리스트 형태인 QuerySet이므로 정말로 1개의 데이터만 조회하고 싶다면 filter 함수 대신 get 함수를 쓰는 것이 좋다. 

 

 

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

>>> Question.objects.get(id=1)

>>> Question.objects.get(id=1)
<Question: pybo가 무엇인가요?>

반환값을 보면 QuerySet이 아니라 Question이다. 여기서 filter함수와 get함수의 차이점을 알 수 있다. filter함수는 여러 건의 데이터를 반환하지만, get함수는 단 한 건의 데이터를 반환한다. 두 함수의 차이점을 꼭 알아두자!

 

 

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

>>> Question.objects.get(id=3)

>>> Question.objects.get(id=3)
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "C:\venvs\mysite\lib\site-packages\django\db\models\manager.py", line 85, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "C:\venvs\mysite\lib\site-packages\django\db\models\query.py", line 429, in get
    raise self.model.DoesNotExist(
pybo.models.Question.DoesNotExist: Question matching query does not exist.
>>>

조건에 맞는 데이터가 없으니 오류가 발생한다. 

 

 

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

>>> Question.objects.filter(id=3)

그러면 filter 함수는 어떨까?

filter 함수는 조건에 맞는 데이터가 없으면 빈 QuerySet을 반환한다. get함수는 반드시 1건의 데이터를 반환해야 한다는 특징이 있으므로 오류가 발생한 것이다.

 

 

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

>>> Question.objects.filter(subject__contains='장고')

그러면 filter 함수는 어떨까?

>>> Question.objects.filter(subject__contains='장고')
<QuerySet [<Question: 장고 모델 질문입니다.>]>
>>>

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

 

☞ 장고는 외워서 사용할 수 있는 프레임워크가 아니므로 장고 문서를 자주 참고하는 습관을 들이자.

☞ 장고 공식 문서(데이터 조회 관련)

https://docs.djangoproject.com/en/3.0/topics/db/queries/

 

Making queries | Django documentation | Django

Django The web framework for perfectionists with deadlines. Overview Download Documentation News Community Code Issues About ♥ Donate

docs.djangoproject.com

 

 

 


데이터 수정하기

 

(1단계) Question 모델 데이터 수정하기

Question 모델 데이터를 수정하려면 우선 수정할 데이터를 조회해야 한다. id=2인 데이터를 조회하고, 수정해 보자.

>>> q = Question.objects.get(id=2)
>>> q
<Question: 장고 모델 질문입니다.>
>>>

 

(2단계) subject 속성 수정하고 DB에 저장하기

>>> q.subject = 'Django Model Question'

>>> q.subject = 'Django Model Question'
>>> q.save()
>>> q
<Question: Django Model Question>
>>>

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

 

 


데이터 삭제하기

 

(1단계) Question 모델 데이터 삭제하기

데이터 삭제는 데이터 수정과 비슷한 과정으로 진행된다. id=1인 데이터를 삭제해 보자.

>>> q = Question.objects.get(id=1)
>>> q.delete()

>>> q = Question.objects.get(id=1)
>>> q.delete()
(1, {'pybo.Question': 1})
>>>

delete함수를 수행하면 해당 데이터가 데이터베이스에서 즉시 삭제되며, 삭제된 데이터의 추가 정보가 반환된다. 앞의 1은 삭제된 Question 모델 데이터의 id를 의미하고, 뒤의 1은 삭제된 모델 데이터의 개수를 의미한다. 

 

 

(2단계) 삭제 획안하기

Question 모델 데이터가 정말로 삭제되었는지 확인해 보자.

>>> Question.objects.all()

>>> Question.objects.all()
<QuerySet [<Question: Django Model Question>]>
>>>

결과를 보면 첫 번째 질문은 삭제되고, 두 번째 질문만 남아 있다. 

 

 

 


연결된 데이터 알아보기

 

앞에서 Answer 모델을 만들 때 ForeignKey(FK)로 Question 모델과 연결하였다. Answer 모델은 Question 모델과 연결되어 있으므로 데이터를 만들 때 Question 모델 데이터가 필요하다. 

 

 

(1단계) Answer 모델 데이터 만들기

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

>>> q = Question.objects.get(id=2)
>>> q
<Question: Django Model Question>
>>> from django.utils import timezone
>>> a = Answer(question=q, content='네 자동으로 생성됩니다.', create_date=timezone.now())
>>> a.save()
>>> a.id
1

Answer 모델 데이터에 a.id = 1 이 생성된 것을 확인할 수 있다. 

 

 

(2단계) Answer 모델 데이터 조회하기

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

>>> Answer.objects.get(id=1)

>>> Answer.objects.get(id=1)
<Answer: Answer object (1)>
>>>

 

 

(3단계) 연결된 데이터로 조회하기: 답변에 있는 질문 조회하기

Answer 모델 데이터에는 Question 모델 데이터가 연결되어 있으므로 Answer 모델 데이터에 연결된 Question 모델 데이터를 조회할 수 있다.

>>> a.question

>>> a.question
<Question: Django Model Question>
>>>

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

 

 

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

아래처럼 answer_set을 통해 질문을 통해 답변을 찾을 수 있다.

>>> q.answer_set.all()

>>> q.answer_set.all()
<QuerySet [<Answer: Answer object (1)>]>
>>>

Question 모델과 Answer 모델처럼 서로 연결되어 있으면 연결모델명_set과 같은 방법으로 연결된 데이터를 조회할 수 있다. 

 

질문 1개에는 1개 이상의 답변이 달릴 수 있으므로 질문에 달린 답변은 q.answer_set으로 조회해야 한다. (답변 세트 조회)

답변은 질문 1개에 대한 것이므로 애초에 여러 개의 질문을 조회할 수 없다. 그래서 a.question만 실행할 수 있다. 연결모델명_set은 신통방통한 장고의 기능이다. 연결모델명_set은 자주 사용할 기능이니 꼭 기억하자. 

 

 

 

 

여기까지.

 

 

 

댓글