3주차 월요일, 11일차 Today I Learned
장고(Django) 프레임웍을 사용한 API 서버 만들기 (1)
: 모델 (Model), 쉘 (Shell)
✏️ 학습 내용
장고 프로젝트를 만들고 서버를 실행하기!
1. Django Project 생성하기
터미널에 원하는 폴더에 이동한 후, 아래 내용을 입력한다. ($는 명령 프롬프트 또는 터미널에서 명령을 입력할 때 사용되는 기호이며, 실제 명령어에 포함되지 않아야 한다.) 우선 django를 먼저 설치해주었다. mysite 라는 프로젝트를 생성하면, 지정한 폴더 안에 manage.py 파일과 __init__.py, asgi.py, settings.py, urls.py, wsgi.py가 생성된다.
0. manage.py : 이 파일을 통해서 장고 프로젝트를 터미널에서 조작 가능하다.
1. __init__.py: 이 파일은 해당 디렉토리를 Python 패키지로 인식하게 하는 빈 파일입니다. Django 애플리케이션 또는 프로젝트의 일부 디렉토리에 이 파일이 있어야 Python이 해당 디렉토리를 패키지로 처리합니다.
2. asgi.py (Asynchronous Server Gateway Interface): 이 파일은 ASGI 서버와의 통신을 처리하는 데 사용됩니다. ASGI는 비동기 웹 애플리케이션을 지원하는 인터페이스로, Django 애플리케이션을 비동기 웹 서버와 통합할 때 사용됩니다.
3. settings.py: 이 파일은 Django 프로젝트의 설정을 정의하는 중요한 파일입니다. 데이터베이스 설정, 애플리케이션 설정, 시간대 설정, 정적 파일 및 미디어 파일 경로 설정 등이 이 파일에서 관리됩니다.
4. urls.py: 이 파일은 URL 패턴을 정의하고 뷰와 매핑하는 역할을 합니다. Django 프로젝트의 URL 구조를 관리하며, 클라이언트 요청을 처리할 뷰 함수로 라우팅합니다.
5. wsgi.py (Web Server Gateway Interface): 이 파일은 WSGI 서버와의 통신을 처리하는 데 사용됩니다. WSGI는 웹 서버와 웹 애플리케이션 사이의 표준 인터페이스로, Django 애플리케이션을 웹 서버에 연결할 때 사용됩니다.
# Django 설치하기
pip install django
# 새로운 Django 프로젝트 생성하기
$ django-admin startproject mysite
# 생성한 프로젝트를 서버에서 실행하기
$ python manage.py runserver
브라우저에서 http://127.0.0.1:8000/ 이동하면 된다.
2. Django App 생성하기
서버를 끄고 아래 내용을 다시 실행한다.
# polls 앱 생성하기
$ python manage.py startapp polls
mysite 폴더 안에 polls 폴더가 생기고 그 안에 여러 파일이 생긴다.
1. __init__.py: 이 파일은 해당 디렉토리를 Python 패키지로 인식하게 하는 빈 파일입니다.
2. admin.py: 이 파일은 Django의 관리자 패널에서 모델을 관리할 때 사용됩니다. 모델 클래스를 등록하고 관리자 패널에서 편집할 수 있도록 설정할 수 있습니다.
3. apps.py: 이 파일은 앱의 설정을 정의하는 곳입니다. 앱 이름, 레이블, 아이콘 및 기타 앱 관련 정보를 설정할 수 있습니다.
4. migrations: 이 디렉토리는 데이터베이스 마이그레이션 관련 파일을 포함합니다. 데이터베이스 스키마를 변경하거나 업데이트할 때 사용됩니다.
5. models.py: 이 파일은 데이터 모델을 정의하는 곳입니다. 데이터베이스 테이블과 상호작용하는 모델 클래스를 작성합니다.
6. tests.py: 이 파일은 테스트 케이스를 작성하는 곳입니다. Django의 내장 테스트 프레임워크를 사용하여 앱을 테스트할 수 있습니다.
7. views.py: 이 파일은 앱의 뷰 함수 및 뷰 클래스를 정의하는 곳입니다. 클라이언트 요청을 처리하고 응답을 생성하는 데 사용됩니다.
8. urls.py: 이 파일은 URL 패턴을 정의하고 뷰 함수 또는 클래스와 매핑합니다. 클라이언트 요청을 적절한 뷰로 라우팅하는 데 사용됩니다.
그리고 각 파일에 아래 내용을 추가한다. polls/urls는 polls 폴더 안에 urls.py 파일을 만든 후에 입력해야 한다.
# polls/views.py
from django.http import HttpResponse
def index(request):
return HttpResponse("Hello, world.")
# mysite/urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path("admin/", admin.site.urls),
path("polls/", include('polls.urls'))
]
# polls/urls.py
from django.urls import path
from . import views
urlpatterns = [
path('',views.index, name='index')
]
어떤 요청이 들어왔을 때 (웹 브라우저를 실행하였을 때), HttpResponse를 하는데 단순히 "Hellow, world." 라는 텍스트를 보내준다. 여기까지 오기에는 처음에 mysite의 urls.py에서 polls에 들어오는 처리는 polls.urls.py에 오도록 했고, 여기에서 아무 것도 안 들어오면 views.index로 가도록 했다.
3. URL 경로 (path) 설정하기
# polls/views.py
from django.http import HttpResponse
def index(request):
return HttpResponse("Hello, world.")
def some_url(request):
return HttpResponse("Some ulr을 구현해 봤습니다.")
# polls/urls.py
from django.urls import path
from . import views
urlpatterns = [
path('',views.index, name='index')
path('some_url',views.some_url)
]
4. 모델 만들기
모델(Model)을 활용해서 관계형 데이터베이스와의 연동을 구현한다. 모델은 데이터베이스에서 테이블에 해당하며, 각 모델은 필드를 가지고 있다.
관계형 데이터베이스 (RDB)
1. 테이블 (Table) : 데이터베이스에서 행과 열로 구성되어 있는 데이터의 집합 (엑셀의 Sheet)
2. 열 (Column) : 테이블에 존재하는 필드
- 필드 (Field) : 앞으로 테이블의 행에 저장될 내용들이 무엇인지 표시하는 기능
3. 행 (row) : 테이블에 저장된 데이터 레코드
- 레코드 (Record) : 하나의 단위로 표현되어지는 필드들의 집합
장고가 DB에서 값을 불러오는 역할을 담당하는 것이 모델이다. 모델은 데이터 정의, 조작, ORM 등의 역할을 수행한다. 이러한 모델을 새롭게 작성하거나 수정하였다면 그 변경된 내용을 데이터베이스에 적용하는 마이그레이션이라는 작업이 필요하다. 마이그레이션을 위해선 먼저 모델의 변경사항을 담고 있는 마이그레이션 파일을 생성해야 한다.
# mysite/settings.py
...
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'polls.apps.PollsConfig', # 이 내용 추가!! 마이그레이션 만들기
]
...
# polls/models.py
# 모델을 테이블에 써주기 위한 마이그레이션 만들기 -> 이 모델에 맞는 테이블 만들기
from django.db import models
class Question(models.Model):
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')
class Choice(models.Model):
question = models.ForeignKey(Question, on_delete=models.CASCADE)
choice_text = models.CharField(max_length=200)
votes = models.IntegerField(default=0)
모델을 만들기 위해서는 models.Model을 입력해야 한다. 그리고 그 내용들을 입력하면 된다.
마이그레이션을 만들기 위해 위의 setting.py 내용을 수정한다.
# migration 파일 생성하기
$ python manage.py makemigrations polls
# migration으로 실행될 SQL 문장 살펴보기
$ python manage.py sqlmigrate polls 0001
# migration 실행하기 (= 테이블 만들기 = 변경된 내용 데이터베이스에 적용하기)
$ python manage.py migrate
5. 모델 필드 활용하기
자세한 내용은 장고 공식 홈페이지 문서에서 확인하면 된다.
https://docs.djangoproject.com/en/4.2/
Django
The web framework for perfectionists with deadlines.
docs.djangoproject.com
아래 주석처리된 부분을 입력하면 된다.
# polls/models.py
from django.db import models
class Question(models.Model):
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')
#is_something = models.BooleanField(default=False)
#average_score = models.FloatField(default=0.0)
class Choice(models.Model):
question = models.ForeignKey(Question, on_delete=models.CASCADE)
choice_text = models.CharField(max_length=200)
votes = models.IntegerField(default=0)
마이그레이션 롤백하는 방법은 아래와 같다.
# Django에서 기본으로 제공하는 SQLite 데이터베이스 파일
>>> sqlite3 db.sqlite3
# Control + D 로 SQL 종료 가능하다.
# 마이그레이션 롤백
#마이그레이션을 0001버전으로 다시 롤백하기
>>>python manage.py migrate polls 0001
마이그레이션을 0001로 돌린 후, 마이그레이션 폴더에 생성된 0002 파일을 삭제하고, models.py에 추가한 내용을 주석처리하면 롤백된다. 이처럼 파일 내용과 DB 내용이 서로 같도록 잘 살펴봐야 한다!
6. Django Admin - 관리자 계정 생성하고 접속하기
장고에서 어드민이라는 관리 사이트를 제공한다. 이 어드민에는 관리자 계정을 가지고 있어야만 접속할 수 있다. 관리자 계정은 아래와 같이 생성한다.
# Django Admin (관리자) 계정 생성하기 (시스템 관리자)
$ python manage.py createsuperuser
# 나오는 내용 입력 (이메일, 비밀번호)
# username : test
# password : test
이렇게 터미널에서 명령어를 입력하여 관리자 계정을 생성할 수도 있고, 아니면 어드민 사이트에서 생성할 수도 있다. url/admin으로 접속하면 Django administration에 접속 가능하다. 여기에서 추가로 관리자를 추가할 수 있다. Add user로 새로운 유저를 만들고 Staff/Superuser Status를 추가하면 된다.
장고 Django 관리자 계정 생성하는 방법 :
1. 터미널에서 `python manage.py createsuperuser` 명령어 입력하기
2. 어드민 사이트 (Django administration : `url/admin`)에서 새로운 유저 만들고 (Add user) `Staff/Superuser Status` 추가하기
http://127.0.0.1:8000/admin
7. 장고 어드민 - 모델 등록하기
# polls/admin.py
from django.contrib import admin
from .models import *
#Register your models here
admin.site.register(Question)
admin.site.register(Choice)
# polls/models.py
from django.db import models
class Question(models.Model):
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')
def __str__(self):
return f'제목: {self.question_text}, 날짜: {self.pub_date}'
class Choice(models.Model):
question = models.ForeignKey(Question, on_delete=models.CASCADE)
choice_text = models.CharField(max_length=200)
votes = models.IntegerField(default=0)
1. admin.py에 내용을 추가한다. 어떤 모델을 어드민에 등록하기 위해서는 `admin.site.register(Question)` 이런 형식을 입력한다.
2. models.py에 __str__ 메서드를 생성한다. 문자열 표시 방식을 정의한 것이다. 어드민 사이트에서 확인하면 내용이 반영되어 있다.
3. models.py의 클래스 안에 내용을 입력하면 어드민 사이트에 반영될 것이다.
8. Django 쉘(Shell)에서 모델 사용하기
사전에 먼저 Choice 클래스를 작성해보겠다.
class Choice(models.Model):
question = models.ForeignKey(Question, on_delete=models.CASCADE)
choice_text = models.CharField(max_length=200)
votes = models.IntegerField(default=0)
def __str__(self):
return self.choice_text
# Django Shell 실행하기
$ python manage.py shell
터미널에서 이 내용을 입력하면 이제 장고 쉘에서 모델을 사용할 수 있다.
물론 사용하려는 모델은 사전에 어드민 사이트 내에 작성된 내용이 있어야 한다.
# models.py 파일에 정의된 모든 모델 가져오기
In [1]: from polls.models import *
In [2]: Question
Out[2]: polls.models.Question
# 모든 Question,Choice 오브젝트 가져오기
In [3]: Question.objects.all()
Out[3]: <QuerySet [<Question: 제목: Test 1, 날짜: 2023-10-30 09:17:48+00:00>]>
In [4]: Choice.objects.all()
Out[4]: <QuerySet [<Choice: choice text test>]>
# 첫번째 Choice 오브젝트 가져오기
In [5]: choice = Choice.objects.all()[0]
In [6]: choice.id
Out[6]: 1
In [7]: choice.choice_text
Out[7]: 'choice text test'
In [8]: choice.votes
Out[8]: 3
# 첫번째 Choice와 연결된 Question 가져오기
In [9]: choice.question
Out[9]: <Question: 제목: Test 1, 날짜: 2023-10-30 09:17:48+00:00>
In [10]: choice.question.pub_date
Out[10]: datetime.datetime(2023, 10, 30, 9, 17, 48, tzinfo=datetime.timezone.utc)
In [11]: choice.question.id
Out[11]: 1
# 해당 Question과 연결되어 있는 모든 Choice 가져오기
In [12]: question = Question.objects.all()[0]
In [13]: question.choice_set.all()
Out[13]: <QuerySet [<Choice: choice text test>]>
Q 모델과 C 모델이 Question ID 라는 FK로 관계를 맺고 있다. 그러므로 Choice에서는 Question에 바로 접근 가능하지만, Question에서는 Choice에 바로 접근할 수 없어서 question.choice_set.all()을 이용한다.
9. 쉘 - 현재 시간 구하기
from datetime import datetime
def solution(param0):
now = datetime.now()
answer = now.replace(microsecond=0) # 현재 시간에서 '마이크로초' 값을 제외
return str(answer)
파이썬에서 현재 시간을 구하려면 위의 코드와 같이 쓴다. 장고에서는 쉘에서 현재 시간을 구하기 위해 아래와 같이 쓴다. 단, 타임존 때문에 장고에서는 현재 시간을 구할 때 timezone.now() 를 이용한다.
# datetime을 활용하여 현재 날짜와 시간 구하기
>>> from datetime import datetime
>>> datetime.now()
# timezone을 활용하여 현재 날짜와 시간구하기
>>> from django.utils import timezone
>>> timezone.now()
10. 쉘 - 레코드 생성하기
class Question(models.Model):
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')
from polls.models import *
# 새로운 Question 오브젝트를 생성하고 'q1'이라는 변수에 저장하기
q1 = Question(question_text = "커피 vs 녹차")
q1.question_text
>>> '커피 vs 녹차'
# tiemzone을 활용하여 새로운 오브젝트 'q1'의 생성시각을 설정하기
from django.utils import timezone
q1.pub_date = timezone.now()
# 새로운 Question 오브젝트 'q1'을 데이터베이스에 저장하기
q1.save()
이처럼 장고에서 쉘을 통해 레코드를 만들 수 있다. q1에는 text와 date를 모두 지정해주어야 오류가 나지 않는다. 이 때, 만약 작성할 때마다 자동으로 날짜가 입력되게 하고 싶으면 Question의 pub_date를 `auto_now_add=True`로 바꾸어 주면 된다.
class Question(models.Model):
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField(auto_now_add=True)
그럼 이제 아래 q3처럼 간단하게 만들 수 있다.
q3 = Question(question_text = "abc")
# q3.pub_date = timezone.now()
q3.save()
# create() 메서드를 활용하여 q3와 연결된 새로운 Choice 오브젝트를 생성하고, choice_text 필드에 값을 넣어주기
>>> q3.choice_set.create(choice_text = "b")
#새로운 Choice 오브젝트를 생성하고 question 필드에 q3 값을 넣어 연결하기
>>> choice_c = Choice(choice_text='c', question=q3)
#새로운 Choice 오브젝트를 데이터베이스에 저장하기
>>> choice_c.save()
11. 쉘 - 레코드 수정 및 삭제하기
from polls.models import *
# Question 오브젝트 중 가장 마지막으로 만들어진 것을 가져오기
q = Question.objects.last()
# 해당 오브젝트의 question_text에 새로운 내용을 더해 수정하기
q.question_text = q.question_text + '???'
# Choice 오브젝트 중 가장 마지막으로 만들어진 것을 가져오기
choice = Question.objects.last()
# 해당 오브젝트에 연결된 Question을 통해서 choice set을 가져오기
choice.queston.choice_set.all()
# 해당 오브젝트를 삭제하기
choice.delete()
q.question_text = "수정할 내용"
q1.choice_set.delete() : q1과 연결되어 있는 기존의 Choice 오브젝트들 모두 삭제
12. 쉘 - 모델 필터링 (Model Filtering) 1
from polls.models import *
# get() 메서드를 사용하여 조건에 해당하는 오브젝트를 필터링하기
Question.objects.get(id=1)
q = Question.objects.get(question_text__startswith='휴가를')
# get으로 여러가지 오브젝트를 가져오려고 한다면 에러발생
Question.objects.get(pub_date__year=2023)
>>> polls.models.Question.MultipleObjectsReturned: get() returned more than one Question
# filter() 메서드를 사용하여 조건에 해당하는 오브젝트를 필터링하기
Question.objects.filter(pub_date__year=2023)
>>> <QuerySet [<Question: 제목: 휴가를 어디서 보내고 싶으세요?, 날짜: 2023-02-05 18:52:59+00:00>, <Question: 제목: 가장 좋아하는 디저트는?, 날짜: 2023-02-05 18:53:27+00:00>, ...]>
Question.objects.filter(pub_date__year=2023).count()
# 쿼리셋의 SQL 쿼리 살펴보기
Question.objects.filter(pub_date__year=2023).query
print(Question.objects.filter(pub_date__year=2023).query)
>>> SELECT "polls_question"."id", "polls_question"."question_text", "polls_question"."pub_date" FROM "polls_question" WHERE "polls_question"."pub_date" BETWEEN 2023-01-01 00:00:00 AND 2023-12-31 23:59:59.999999
Question.objects.filter(question_text__startswith='휴가를').query
print(Question.objects.filter(question_text__startswith='휴가를').query)
>>> SELECT "polls_question"."id", "polls_question"."question_text", "polls_question"."pub_date" FROM "polls_question" WHERE "polls_question"."question_text" LIKE 휴가를% ESCAPE '\'
'
q = Question.objects.get(pk=1)
q.choice_set.all()
print(q.choice_set.all().query)
>>> SELECT "polls_choice"."id", "polls_choice"."question_id", "polls_choice"."choice_text", "polls_choice"."votes" FROM "polls_choice" WHERE "polls_choice"."question_id" = 1
필터링은 두 가지가 있다. 이 둘은 반환하는 객체의 수가 다르다. get은 하나의 오브젝트만 반환하고, filter는 여러 오브젝트를 포함하는 쿼리셋을 반환한다.
1. get() : 하나만 가져올 수 있다. 여러 개 가져올 경우 에러 발생한다.
2. filter() : 여러 개 가져올 수 있다. 여러 개이면 QuerySet이 주어진다.
(Q에서 C는 여러 개, C에서 Q는 한 개여서 오브젝트를 가져온다)
SQL 쿼리를 살펴보며 어떻게 작동되는지 살펴볼 수 있다.
13. 쉘 - 모델 필터링 2
from polls.models import *
# startswith 연산자를 활용하여 오브젝트를 필터링하기
q = Question.objects.filter(question_text__startswith='휴가를')
q2 = Question.objects.filter(pub_date__year=2023)
# contains 연산자를 활용하여 오브젝트를 필터링하기
Question.objects.filter(question_text__contains='휴가')
# gt (Greater than) 연산자를 활용하여
Choice.objects.all()
Choice.objects.filter(votes__gt=0)
# 해당 쿼리셋에 대한 SQL 쿼리를 생성하기
Choice.objects.filter(votes__gt=0).query
print(Choice.objects.filter(votes__gt=0).query)
>>> SELECT "polls_choice"."id", "polls_choice"."question_id", "polls_choice"."choice_text", "polls_choice"."votes" FROM "polls_choice" WHERE "polls_choice"."votes" > 0
choice=Choice.objects.first()
choice.votes=5
choice.save()
# 정규표현식을 활용하여 조건에 해당하는 오브젝트들을 필터링하기
Question.objects.filter(question_text__regex=r'^휴가.*어디')
print(Question.objects.filter(question_text__regex=r'^휴가.*어디').query)
>>> SELECT "polls_question"."id", "polls_question"."question_text", "polls_question"."pub_date", "polls_question"."owner_id" FROM "polls_question" WHERE "polls_question"."question_text" REGEXP ^휴가.*어디
filter() 메서드에 연산자를 활용할 수 있다. 이 외에도 많은데, 공식 문서를 참고하면 된다.
1. startwith = "text" : 해당 text로 시작하는 오브젝트를 필터링한다.
2. contains = "text" : 해당 text를 포함하는 오브젝트를 필터링한다.
3. gt = n : Greater than으로, 입력한 숫자 n 보다 큰 오브젝트를 필터링한다.
4. __regex= r'정규표현식' : 정규표현식을 활용해서 해당하는 내용을 포함하는 오브젝트를 필터링한다.
Choice.object.filter(votes__gt=0).update(votes=0) # 수정
Choice.object.filter(votes=0).delete() # 삭제
14. 쉘 - 모델 필터링 3 : 모델 관계기반 필터링
필터를 하는 새로운 방법 2가지가 더 있다.
1. 모델 사이의 관계에 의한 필터링 : C 모델은 FK로 Q 모델을 가져오고 있다. 두 모델 사이의 관계를 알고 있다면 이를 기반으로 필터링을 수행할 수 있다.
2. exclude 사용 : 쿼리셋에서 특정한 조건에 해당되는 오브젝트들을 제외하는 메서드
모델 사이의 관계에 의한 필터링을 하기 위해서 우선 Choice 클래스의 __str__ 메서드를 아래처럼 수정한다.
# polls/models.py
from django.db import models
class Question(models.Model):
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')
def __str__(self):
return f'제목: {self.question_text}, 날짜: {self.pub_date}'
class Choice(models.Model):
question = models.ForeignKey(Question, on_delete=models.CASCADE)
choice_text = models.CharField(max_length=200)
votes = models.IntegerField(default=0)
def __str__(self):
return f'[{self.question.question_text}] {self.choice_text}'
그리고 Shell에서 내용을 입력하는데, 참고로 Shell은 변경된 내용을 자동으로 반영하지 않으니 다시 실행해야 한다.
from polls.models import *
# Question의 question_text 필드 값이 '휴가'로 시작하는 모든 Choice 오브젝트를 필터링하기
Choice.objects.filter(question__question_text__startswith='휴가')
# 어떻게 동작하는지 SQL로 확인하기
print(Choice.objects.filter(question__question_text__startswith='휴가').query)
# exclude() 메서드를 사용하여 question_text 필드 값이 '휴가'로 시작하는 모든 Choice 오브젝트를 제외하고 필터링하기
Question.objects.exclude(question_text__startswith='휴가')
15. 쉘 - 모델 메소드
모델에서 메소드를 추가하는 방법이다.
# polls/modes.py
from django.utils import timezone
import datetime
class Question(models.Model):
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')
def was_published_recently(self):
return self.pub_date >= timezone.now() - datetime.timedelta(days=1)
def __str__(self):
if self.was_published_recently():
new_badge = 'NEW!!!'
else:
new_badge = ''
return f'{new_badge} 제목: {self.question_text}, 날짜: {self.pub_date}'
`.was_published_recently()`로 최근 1일 이내에 만들어진 것인지 True or False로 파악한다. 그리고 __str__에 최근에 만들어진 것에 "NEW!!!"를 붙이도록 하였다.
from polls.models import *
q = Question.objects.first()
q.was_published_recently()
>>> False
new_q = Question(question_text="new q")
new_q.save()
new_q.was_published_recently()
>>> True
참고. Timezone
from datetime import datetime, timedelta
now = datetime.now()
>>> datetime.datetime(2023, 3, 2, 14, 35, 21, 534607)
future = now + timedelta(days=1, hours=1, minutes=30)
>>> datetime.datetime(2023, 3, 3, 16, 5, 21, 534607)
datetime.datetime()은 datetime 모듈의 datetime 클래스를 나타내며, 괄호 안에 있는 값은 각각 year:연도/ month:월/ day:일/ hour:시/ minute:분 / second:초 / microsecond:마이크로초를 의미한다.
timedelta는 괄호()안에 days , hours, minutes와 같은 인자들을 넣어 원하는 시간 간격을 표시할 수 있다. 물론 인자들을 개별적으로 전달하여 원하는 날짜,시간,분의 간격만을 얻어내는 것도 가능하다.
☁️ 소감
강의를 따라가는 데에 어려움은 없었지만, 혼자서 구현하라고 한다면 못할 것 같았다. 초반에는 왜 이런 작업을 하는 것인지 이해가 가지 않았다. (사실 지금도 조금 그렇다) 하지만 계속 수강을 하다보니 이해되는 것들도 있어서 일단 의문점은 적어두고 수강하면서 그에 대한 해답, 깨달음을 적어보려고 한다. 그래서 다음 TIL에서는 의문점도 기록하려고 한다.