Study/Django

[Django] 모델 (6)

taecongs 2023. 9. 8. 14:11

Django 공부하기 ✨
참고 사이트 : 파이보 (점프 투 장고)


Django에서 모델이란?

  • 장고는 모델(Model)을 이용하여 데이터베이스를 처리한다. 보통 데이터베이스에 데이터를 저장하고 조회하기 위해서 SQL 쿼리문을 이용해야 하지만 장고의 모델(Model)을 사용하면 이런 SQL 쿼리문 도움 없이 데이터를 쉽게 처리할 수 있다.

 

(1) Django 앱 migrate

  • projects/mysite/config/settings.py 파일을 확인해보자.
  • 데이터베이스 엔진은 django.db.backends.sqlite3 라고 정의되어 있다.
  • 그리고 데이터베이스 파일은 BASE_DIR 디렉터리 밑에 db.sqlite3 파일에 저장한다고 정의되어 있다.
  • 현재 진행하고 있는 프로젝트의 BASE_DIR 은 C:\projects\mysite이다.
// (1) 데이터베이스 테이블 생성하기
(mysite) C:\projects\mysite>python manage.py migrate

 

(2) 모델(Model) 작성하기

  • 모델은 크게 질문(Question) 속성과 답변(Answer) 속성을 가지고 있다.
  • projects/mysite/pybo/models.py질문(Question) 속성과 답변(Answer) 속성을 정의한다.

// (2) pybo/models.py 정의하기
from django.db import models

class Question(models.Model):
    subject = models.CharField(max_length=200)
    content = models.TextField()
    create_date = models.DateTimeField()
    
class Answer(models.Model):
    question = models.ForeignKey(Question, on_delete=models.CASCADE)
    content = models.TextField()
    create_date = models.DateTimeField()
  • 기존 모델을 속성으로 연결하기 위해 ForeignKey를 사용했다. 
  • ForeignKey는 다른 모델과 연결하기 위해 사용된다.
  • on_delete=models.CASCADE는 답변과 연결된 질문(Question)이 삭제될 경우 답변(Answer)도 함께 삭제한다.

 

(3) 테이블 생성하기

  • 테이블 생성을 위해 pybo 앱을 config/settings.py 파일의 INSTALLED_APPS 항목에 추가한다.
// (3) config/settings.py 파일 수정하기
INSTALLED_APPS = [
    'pybo.apps.PyboConfig',   // 추가된 항목
    'django.contrib.admin',
    'django.contrib.auth',
    (... 생략 ...)
]
  • NSTALLED_APPS에 추가한 pybo.apps.PyboConfig 클래스 pybo/apps.py 파일에 있는 클래스이다.
  • 이 파일은 pybo 앱 생성시 자동으로 만들어지는 파일로 따로 만들 필요가 없다. 

 

(4) makemigrations

  • 테이블 생성을 위해 migrate 명령을 수행하면 오류가 발생 되는 경우가 있다. 이때 모델이 신규로 생성되거나 변경되면 makemigrations 명령을 먼저 수행한 후에 migrate 명령을 수행해야하는 점을 유의해야 한다.
  • makemigrations 명령을 수행하더라도 실제로 테이블이 생성되지는 않는다. makemigrations 명령은 장고가 테이블 작업을 수행하기 위한 작업 파일(예: 0001_initial.py)을 생성하는 명령어다. 실제 테이블 작업은 migrate 명령을 통해서만 가능하다.
// (4) 테이블 생성을 위해 makemigrations 실행
(mysite) C:\projects\mysite>python manage.py makemigrations

 

(5) sqlmigrate

  • makemigrations로 데이터베이스 작업 파일을 생성하고 migrate 명령을 실행하기 전에 실제 어떤 쿼리문이 실행되는지 sqlmigrate 명령으로 확인해 볼수 있다.
  • sqlmigrate 명령은 단지 실행되는 쿼리만 조회할 뿐이다. 실제 쿼리가 수행되지는 않는다.
  • "pybo"는 앱 이름을 의미하고 "0001"은 생성된 작업파일(예: 0001_initial.py)의 일련번호를 의미한다.
// (5) 어떤 쿼리문이 실행되는지 확인하기 위해 sqlmigrate 실행
(mysite) C:\projects\mysite>python manage.py sqlmigrate pybo 0001

 

(6) migrate

  • makemigrations 명령을 먼저 수행하였기 때문에 오류 없이 잘 수행될 것이다.
// (6) 테이블 생성을 위해 migrate 실행
(mysite) C:\projects\mysite>python manage.py migrate

 

(7) 모델 사용하기

  • 일반적인 파이썬 셸을 실행하는 것이 아니라 python manage.py shell처럼 장고 셸을 실행해야한다.
  • 장고 셸은 필요한 환경들이 자동으로 설정되어 실행된다.
// (7) 모델 사용법 장고 셸로 익혀보기
(mysite) C:\projects\mysite>python manage.py shell

Python 3.11.4 (tags/v3.11.4:d2340ef, Jun  7 2023, 05:45:37) [MSC v.1934 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>>

 

(8) Question 생성

  • 질문(Question)과 답변(Answer) 모델은 장고 셸에서 import하여 사용할 수 있다.
// (8-1) Question과 Answer import 하기
>>> from pybo.models import Question, Answer
// (8-2) Question 모델을 이용하여 질문 데이터 만들기1
>>> from django.utils import timezone
>>> q = Question(subject='pybo가 무엇인가요?', content='pybo에 대해서 알고 싶습니다.', create_date=timezone.now())
>>> q.save()

// Question 모델의 객체 q를 생성한 후 save함수를 실행하면 질문 데이터가 1건 생성
>>> q.id
1


// (8-3) Question 모델을 이용하여 질문 데이터 만들기2
>>> q = Question(subject='장고 모델 질문입니다.', content='id는 자동으로 생성되나요?', create_date=timezone.now())
>>> q.save()

// Question 모델의 객체 q를 생성한 후 save함수를 실행하면 질문 데이터가 1건 생성
>>> q.id
2
  • id는 모델 데이터의 유일한 값으로 프라이머리 키(PK:Primary Key)라고도 한다.
  • 이 id 값은 데이터를 생성할 때마다 1씩 증가된다.
  •  create_date 속성은 DateTimeField 타입이므로 timezone.now()로 현재일시를 대입한다.

 

(9) Question 조회

  • 저장한 데이터를 조회 할 수 있다.
  • 결과값으로는 QuerySet 객체가 리턴되고, 1과 2는 Question 데이터의 id 값이다.
// (9-1) 저장한 데이터 조회하기
>>> Question.objects.all()

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



// (9-2) 저장한 데이터를 id 값 대신 제목으로 조회하기
(... 생략 ...)

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

    def __str__(self):              // 추가된 항목
        return self.subject

(... 생략 ...)
  • pybo/models.py 파일의 Question 모델에__str__ 메서드를 추가하면 id 값 대신 제목을 표시할 수 있다.
// (9-3) 장고 셸 종료하기
>>> ctrl+z 또는 quit() 입력
  • 장고 셸을 종료하기 위해서는 장고 셸에서 Ctrl+Z 또는 quit()을 입력하면 된다.
  • 모델이 변경되었다면? 장고 셸을 재시작해야 변경된 결과를 확인할 수 있다.
// (9-4) 장고 셸 다시 실행하기
(mysite) C:\projects\mysite>python manage.py shell

// (9-5) 장고 셸 다시 실행하기
>>> from pybo.models import Question, Answer

// (9-6) 장고 셸 다시 실행하기
>>> Question.objects.all()

<QuerySet [<Question: pybo가 무엇인가요?>, <Question: 장고 모델 질문입니다.>]>
  • 1과 2라는 id 값 대신 이제 제목이 표시되는 것을 확인할 수 있다.
// (9-7) filter 사용하여 데이터 조회하기
>>> Question.objects.filter(id=1)

<QuerySet [<Question: pybo가 무엇인가요?>]>


// (9-8) filter 대신 get을 사용하여 데이터 조회하기
>>> Question.objects.get(id=1)

<Question: pybo가 무엇인가요?>
  • filter는 조건에 해당되는 데이터를 모두 리턴해준다.
  • id는 유일한 값이므로 filter 대신 get을 이용하여 조회할 수도 있다.
  • get은 반드시 1건의 데이터를 조회할 때 사용해야 한다.

 

(10) Question 수정

  •  subject 속성을 사용하여  수정 한 후 반드시 save를 수행해 주어야 변경된 데이터가 반영된다.
// (10-1) Question 데이터 수정하기
>>> q = Question.objects.get(id=2)
>>> q

<Question: 장고 모델 질문입니다.>


// (10-2) suject 속성 수정하기
>>> q.subject = 'Django Model Question'
>>> q.save()
>>> q

<Question: Django Model Question>

 

(11) Question 삭제

  • delete를 수행하면 해당 데이터가 삭제된다.
  • 삭제될 때는 위와 같이 추가정보가 리턴된다.
  • (1, {'pybo.Question': 1})은 Question 모델이 1개 삭제되었음을 의미한다.
// (11) id 값이 1인 Question 데이터 삭제하기
>>> q = Question.objects.get(id=1)
>>> q.delete()

(1, {'pybo.Question': 1})

 

(12) Answer 작성

  • 답변 데이터를 만들기 위해서는 반드시 질문 데이터가 필요하다.
  • 그러므로 id가 2인 질문을 먼저 조회한 후 question 속성에 대입하였다.
// (12-1) 기존 질문 확인하기
>>> q = Question.objects.get(id=2)
>>> q

<Question: Django Model Question>

// (12-2) 답변 데이터 생성하기
>>> from django.utils import timezone
>>> a = Answer(question=q, content='네 자동으로 생성됩니다.', create_date=timezone.now())
>>> a.save()
>>> a.id
1

 

(13) Answer 조회

  • 답변을 조회하는 방법은 질문과 마찬가지로 Answer의 id 값을 사용하면 된다.
// (13-1) 답변 조회하기
>>> a = Answer.objects.get(id=1)
>>> a

<Answer: Answer object (1)>


// (13-2) 답변에 연결된 질문 확인하기
>>> a.question

<Question: Django Model Question>