본문 바로가기

Minding's Programming/Django

[Django] Django Shell 사용해보기

728x90
반응형

Django Shell?

Django shell은 python shell 등과 비슷한 형태를 가지고 있지만, Django 환경을 다룰 수 있는 shell이다.

❯ python manage.py shell

Python 3.9.0 (default, Nov 15 2020, 14:28:56) 
[GCC 7.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>>

위와 같이 manage.py의 shell 함수를 실행시켰는데, 파이썬 shell과 거의 유사한 모습을 보여준다.

 

Django Shell로 모델 활용하기

1. 조회

>>> from polls.models import *
>>> Question
<class 'polls.models.Question'>

Question 모델을 불러올 때도 python shell을 사용하는 것처럼 해당 클래스를 임포트 해주어야 읽을 수 있다.

 

먼저 Question 모델 내 레코드를 조회해보자. Admin에서 추가한 레코드가 노출된다.

>>> Question.objects.all()
<QuerySet [<Question: 가장 추천하는 가을 캠핑장은 어디인가요?>]>

 

Admin에서 조회할 때처럼 문자열이 질문 내용으로 표시되는 것을 알 수 있다. 하지만 Django Shell에서 유의할 점은 업데이트 내용이 즉시 반영되지 않는다는 것이다. 업데이트 내용을 반영하기 위해서는 shell을 끈 뒤 다시 실행시켜야 한다.

 

이번엔 Choice를 통해 제목 뿐만 아닌 세부항목들도 조회해보자.

# choice 변수에 choice 모델 내 첫번째 항목 지정
>>> choice = Choice.objects.all()[0]
>>> choice.id
1
>>> choice.choice_text
'포천'
>>> choice.votes
0
# question에 FK로 연결된 항목이 노출되는 것을 알 수 있음
>>> choice.question
<Question: 가장 추천하는 가을 캠핑장은 어디인가요?>

Choice의 각 항목들을 조회했을 때, 잘 노출되는 것을 확인할 수 있다. 특히 FK로 지정된 question을 조회하면, Question 모델에 있는 항목으로 바로 연결되는 것을 알 수 있다. 아래와 같은 조회도 가능하다.

 

>>> choice.question.pub_date
datetime.datetime(2024, 10, 7, 4, 20, 27, tzinfo=datetime.timezone.utc)

Choice 모델의 question 항목을 통해 Question 모델에 있는 레코드에 직접 연결하기 때문에, 그 질문에 해당하는 pub_date 항목도 조회할 수 있게된다. 하지만 반대의 경우는 그렇지 않다. Question 모델에서 똑같은 방법으로 choice를 조회하면, 에러가 노출되게 된다.

 

그렇다면 해당 question과 연결되어 있는 항목들을 조회하는 방법은 없을까? 다른 메서드를 이용하면 조회할 수 있다.

>>> from polls.models import *
>>> question = Question.objects.all()[0]
# 해당 question과 연결되어 있는 모든 choice 가져오기
>>> question.choice_set.all()
<QuerySet [<Choice: 포천>]>

위와 같이 .choice_set.all()을 이용한다면, Question에서도 choice항목을 조회해볼 수 있다.

 

2. 레코드 생성(추가)

아래 내용 참고!

더보기

파이썬에서는 datetime이라는 라이브러리를 통해 현재 시간을 구하지만, Django에서는 기본으로 제공되는 라이브러리인 utils의 timezone이 있다. timezone은 지역을 반영한 시간을 설정할 수 있기 때문에, django에서는 timezone 함수를 사용한다.

 

>>> from django.utils import timezone
>>> timezone.now()
datetime.datetime(2024, 10, 7, 5, 7, 59, 281006, tzinfo=datetime.timezone.utc)

 

Django Shell에서도 admin과 같이 모델에 대한 CRUD를 진행할 수 있다. 먼저 레코드 추가를 해보려고 한다. "야구vs축구"라는 질문을 하나 생성해본다고 가정해보자.

>>> from polls.models import *

#"야구 vs 축구" 라는 내용의 새로운 Question 오브젝트를 생성하고 'q1'이라는 변수에 저장
>>> q1 = Question(question_text = "야구 vs 축구")

#tiemzone을 활용하여 새로운 오브젝트 'q1'의 생성시각을 설정
>>> from django.utils import timezone
>>> q1.pub_date = timezone.now()

#새로운 Question 오브젝트 'q1'을 데이터베이스에 저장
>>> q1.save()

question_text를 지정한 변수에 Question 모델 객체를 지정해 준 다음, timezone.now()를 통해서 생성일시를 넣어준다. 그 다음 save() 메서드를 통해 DB에 저장해준다.

 

Admin을 열어 Question 모델을 확인해보니 '야구 vs 축구'라고 적힌 레코드가 하나 추가된 것을 알 수 있다.

 

날짜 자동 입력

생성일자의 경우 일일히 timezone.now()를 쓰기엔 번거로운 부분이 있다. models.py에서 pub_date를 자동으로 지정할 수 있도록 수정해주자.

# mysite/polls/models.py

from django.db import models

# model 생성
class Question(models.Model):
    question_text = models.CharField(max_length=200)
    # DateTimeField의 인자로 auto_now_add를 True로 전달
    # 해당 객체가 만들어질 때를 기준으로 pub_date 자동 생성
    pub_date = models.DateTimeField(auto_now_add=True)

    # 문자열을 표시할 때 question_text를 반환
    def __str__(self):
        return self.question_text

위처럼 DateTimeField() 메서드에 auto_now_add 인자를 True로 전달해주면, 해당 객체(레코드)가 생성될 때를 기준으로 자동 생성해준다. 

 

models.py의 수정내용을 반영하기 위해서 우선 shell을 재시작해준 뒤, 아래 코드를 실행시켜보자.

>>> from polls.models import *
>>> q3 = Question(question_text='abc')
>>> q3.save()
>>> q3.pub_date
datetime.datetime(2024, 10, 7, 5, 27, 29, 992184, tzinfo=datetime.timezone.utc)

위 코드에서는 pub_date를 따로 입력하지 않았는데도 datetime이 찍혀 나오는 걸 알 수 있다.

 

FK로 연결된 모델의 레코드 생성

Question과 Choice는 FK 관계로 연결되어 있다. 이를 이용하면 Question 객체를 이용해 Choice 레코드를 바로 생성할 수 있다.

# q3 질문(abc)에 대한 choice를 생성
>>> q3.choice_set.create(choice_text='a')
<Choice: a>

# q3의 FK로 연결된 첫번째 choice의 question을 조회
>>> q3.choice_set.first().question
<Question: abc>

 

물론 Choice 모델을 이용해 직접 레코드를 추가하는 방법도 있다.

#새로운 Choice 오브젝트를 생성하고 question 필드에 q3 값을 넣어 연결
>>> choice_c = Choice(choice_text='c', question=q3)

#새로운 Choice 오브젝트를 데이터베이스에 저장
>>> choice_c.save()

 

3. 레코드 수정

# Question 모델 중 마지막 항목 선택
>>> q = Question.objects.last()
>>> q.question_text
'abc'

# 'abc' -> 'abc???'가 되도록 수정
>>> q.question_text = q.question_text + '???'
# save() 메서드를 통해 DB에 저장 (하지 않으면 반영되지 않음)
>>> q.save()

Admin 페이지를 통해 확인한 결과 수정이 정상적으로 반영된 것을 확인할 수 있다.

 

4. 레코드 삭제

# Choice 모델 중 마지막 항목 선택 (== a)
>>> choice = Choice.objects.last()
# choice의 question을 조회해 해당 question과 연결된 답변 모두 확인
>>> q = choice.question

# c 레코드 추가
>>> choice_c = Choice(choice_text='c', question=q3)
>>> choice_c.save()

>>> q.choice_objects.all()
>>> q.choice_set.all()
<QuerySet [<Choice: a>, <Choice: c>]>

# delete() 메서드 이용해 지정한 레코드 삭제
>>> choice.delete()
(1, {'polls.Choice': 1})

# 하나만 남아있는 것을 확인할 수 있음
>>> q.choice_set.all()
<QuerySet [<Choice: c>]>

delete() 메서드를 이용해 레코드를 삭제할 수 있다.

728x90