[Django] 첫 번째 장고 앱 작성하기, part2
링크 : https://docs.djangoproject.com/ko/4.1/intro/tutorial02/
📖 개요
이 글은 장고 공식 문서를 보고 실습한 내용을 다시 한번 기억하기 위해 쓰면서 정리한 내용입니다.
🎯 목표
- 데이터 베이스를 설치하고 첫 모델을 생성하기
- Django에서 자동 생성되는 관리자 사이트에 대해서 알아보기
💡 데이터 베이스 설치
mysite.settings.py 파일은 Django설정을 모듈 변수로 표현한 보통의 python모듈입니다.
기본적으로는 SQLite을 사용하도록 구성이 되어 있습니다. 만약 데이터 베이스를 처음 하거나 Django의 데이터 베이스를 해보고 싶다면 SQLite가 가장 간단한 방법입니다. SQLite는 Python에서 기본으로 제공되기 때문에 별도로 설치할 필요가 없습니다.
다른 데이터베이스를 사용해 보고싶다면 적절한 데이터베이스 바인딩을 설치하고, 데이터베이스 연결 설정과 맞게끔 BATABASES 'default' 항목의 값을 다음의 키 값으로 바꿔줘야 한다.
- ENGINE – 'django.db.backends.sqlite3', 'django.db.backends.postgresql', 'django.db.backends.mysql', 또는 'django.db.backends.oracle'. 그외에 서드파티 백엔드 참조.
- NAME – 데이터베이스의 이름입니다. SQLite를 사용하는 경우 데이터베이스는 컴퓨터의 파일이 됩니다. 이 경우 :setting:`NAME`은 파일 이름을 포함한 해당 파일의 전체 절대 경로여야 합니다. 기본값인 ``BASE_DIR / ‘db.sqlite3’``은 파일을 프로젝트 디렉토리에 저장합니다.
💡 mysite/settings 설정
- TIME_ZONE 설정
- mysite/settings.py를 열어서 나의 시간 값과 맞게 TIME_ZONE를 설정하면 된다.
- 나(한국)의 경우는 TIME_ZONE='Asia/Seoul'로 해주었다.
- INSTALLED_APPS
- django.contrib.admin - 관리용 사이트
- django.contrib.auth - 인증 시스템
- django.contrib.contenttypes - 콘텐츠 타입을 위한 프레임워크
- django.contrib.sessions - 세션 프레임워크
- django.contrib.messages - 메세징 프레임워크
- django.contrib.staticfiles - 정적 파일을 관리하는 프레임워크
💡 migrate 명령
py manage.py migrate
위의 명령어는 INSTALLED_APPS의 설정을 탐색하여, mysite/settings.py의 데이터베이스 설정과 app과 함께 제공되는 database migrations(아직 안 배움)에 따라 필요한 데이터베이스 테이블을 생성한다. 위 명령을 수행하면 각 migration이 적용되는 메시지가 화면에 출력되는 것을 확인할 수 있다.
❗어떤 내용이 생성되는지 궁금하다면 아래 명령어를 통해 Django 가 생성한 테이블을 확인해 볼 수 있다.
- 데이터 클라이언트 접속 후
- \dt (PostgreSQL), SHOW TABLES;
- (MariaDB, MySQL), .tables (SQLite), SELECT TABLE_NAME FROM USER_TABLES;
💡 모델 만들기
모델을 정의하자면 본직적으로 부가적인 메타데이터를 가진 데이터 베이스 구조를 말한다.
내가 만드는 앱에서는 Question과 Choice이라는 두 가지 모델을 만든다.
Question에는 질문과 발행일을 위한 두 개의 필드를 가지고 Choice는 선택 텍스트와 투표 집계를 위한 두 개의 필드를 가진다. 각각의 Choice모델은 Question과 연관이 된다.
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)
위 코드에서 각 모델은 class:django.db.models.Model의 하위 클래스로 표현되며 모델마다 여러 클래스 변수가 있다.
각 클래스 변수는 모델에서 데이터 베이스 필드를 나타낸다.
데이터 베이스의 각 필드는 Field 클래스의 인스턴스로서 표현된다. CharField는 문자 필드를 표현하고, DateTimeField는 날짜와 시간 필드를 표현한다.
CharField의 경우 max_length를 반드시 입력해주어야 한다. 이것은 데이터 베이스 스키마에서만 필요한 것이 아닌 값을 검증할 때도 쓰인다. 또한 Field는 다양한 선택적 인수들을 가질 수 있다. 위에서는 default로 하여 votes의 기본값을 0으로 설정하였다.
ForeignKey를 사용하여 관계 설정을 한다 위 코드에서는 Choice가 하나의 Quewstion에 관계된다는 것을 Django에게 알려준다.
💡 모델 활성화
모델은 Django에게 많은 양의 정보를 전달해주고 Django는 이러한 데이터를 가지고 아래와 같은 일을 할 수 있다.
- 이 앱을 위한 데이터 베이스 스키마 생성 (CREATE TABLE 문)
- Question과 Choice 객체에 접근하기 위한 Python 데이터 베이스 접근 API를 생성
앱을 현재의 프로젝트에 포함시키기 위해서는, 앱의 구성 클래스에 대한 참조를 INSTALLED_APPS설정에 추가해주어야 한다. PollsConfig 클래스는 polls/apps.py 파일 안에 존재한다. 따라서 PollsConfig 클래스를 사용하기 위하여 'polls.apps.PollsConfig'를 mysite/settings.py 파일 안에 있는 INSTALLED_APPS설정에 추가하여 된다
INSTALLED_APPS = [
'polls.apps.PollsConfig',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
💡 변경사항을 migration으로 저장
py manage.py makemigrations polls
위와 같이 makemigrations를 실행 시킴으로써 내가 모델을 변경시킨 사실과 변경사항을 migration으로 저장
py manage.py sqlmigrate polls 0001
위 코드를 실행시 디스크에 저장된 새 모델에 대한 migration을 읽어 볼 수 있다.
아래의 글은 잘 이해하지는 못했지만 나중을 위해서 옮겨두었다.
- 사용하는 데이터베이스에 따라서 출력결과는 다를 수 있습니다. 위의 출력결과는 PostgreSQL에서 생성되었습니다.
- 테이블 이름은 앱의 이름과 모델의 이름(소문자)이 조합되어 자동으로 생성됩니다. 이 경우, 앱의 이름인 polls 와 소문자로 표기된 모델의 이름인 question 과 choice가 합쳐집니다. (이 동작을 재지정(override)하여 수정할 수 있습니다.)
- 기본 키(ID)가 자동으로 추가됩니다. (역시 이 동작도 재지정할 수 있습니다.)
- 관례에 따라, Django는 외래 키 필드명에 "_id" 이름을 자동으로 추가합니다. (물론 이것도 재지정할 수 있습니다.)
- 외래 키 관계는 FOREIGN KEY 라는 제약에 의해 명시됩니다. DEFERRABLE 부분에 대해서는 걱정하지 마십시오. 이것은 PostgreSQL에 트랜잭션이 끝날 때까지 외래 키를 강제하지 말라고 알려주는 것입니다.
- 사용 중인 데이터베이스에 맞게 조정되므로 auto_increment(MySQL), bigint PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY(PostgreSQL) 또는 정수 기본 키 자동 증가(SQLite)와 같은 데이터베이스별 필드 유형이 자동으로 처리됩니다. 큰따옴표나 작은따옴표를 사용하여 필드 이름을 인용할 때도 마찬가지입니다.
- sqlmigrate 명령은 실제로 데이터베이스에서 마이그레이션을 실행하는 것이 아니라 화면에 인쇄하여 필요한 SQL Django를 확인할 수 있도록 합니다. 이것은 Django가 수행할 작업이나 변경을 위해 SQL 스크립트를 필요로 하는 데이터베이스 관리자가 있는지 확인하는 데 유용합니다.
💡 데이터베이스에 모델과 관련된 테이블 생성
py manage.py migrate
💡 API
아래의 명령을 통해 대화형 Python 쉘에 들어가 Django API를 바꾸어줄 수 있다.
py manage.py shell
단순히 "python을" 입력하는 대신 이것을 사용하는 이유는 manage.py에 설정된 DJANGO_SETTINGS_MODULE 환경 변수 때문입니다. 이 변수는 Django에게 mysite/settings.py의 Python 가져오기 경로를 제공합니다.
>>> from polls.models import Choice, Question # Import the model classes we just wrote.
# 아직 시스템에 질문이 없습니다.
>>> Question.objects.all()
<QuerySet []>
# 새 질문을 만듭니다.
# 기본 설정 파일에서 시간대 지원이 활성화되어 있으므로
# Django는 pub_date에 대해 tzinfo가 있는 datetime을 기대합니다. - timezone.now() 사용
# datetime.datetime.now() 대신에 올바른 일을 할 것입니다.
>>> from django.utils import timezone
>>> q = Question(question_text="What's new?", pub_date=timezone.now())
# 객체를 데이터베이스에 저장합니다. 명시적으로 save()를 호출해야 합니다.
>>> q.save()
# 이제 아이디가 생겼습니다.
>>> q.id
1
# Python 속성을 통해 모델 필드 값에 액세스합니다.
>>> q.question_text
"What's new?"
>>> q.pub_date
datetime.datetime(2022, 11, 14, 7, 30, 44, 575494, tzinfo=datetime.timezone.utc)
# 속성을 변경한 다음 save()를 호출하여 값을 변경합니다.
>>> q.question_text = "What's up?"
>>> q.save()
# objects.all()은 데이터베이스의 모든 질문을 표시합니다.
>>> Question.objects.all()
<QuerySet [<Question: Question object (1)>]>
💡 <Question: Question object (1)>
위 쪽의 <Question: Question object (1)>는 객체를 표현하는데 별로 도움이 되지 않기 때문에 모델에 메서드를 추가하여 조금 더 좋게 표현할 수 있다.
import datetime
from django.db import models
from django.utils import timezone
class Question(models.Model):
# ...
def __str__(self):
return self.question_text
def was_published_recently(self):
return self.pub_date >= timezone.now() - datetime.timedelta(days=1)
class Choice(models.Model):
# ...
def __str__(self):
return self.choice_text
변경 사항을 저장하고, python manage.py shell을 다시 실행해 보자.
>>> from polls.models import Choice, Question
# __str__() 추가가 제대로 작동하는지 확인하십시오.
>>> Question.objects.all()
<QuerySet [<Question: What's up?>]>
# Django는 전적으로 다음으로 구동되는 풍부한 데이터베이스 조회 API를 제공합니다.
# 키워드 인수.
>>> Question.objects.filter(id=1)
<QuerySet [<Question: What's up?>]>
>>> Question.objects.filter(question_text__startswith='What')
<QuerySet [<Question: What's up?>]>
# 올해 공개된 질문을 받아보세요.
>>> from django.utils import timezone
>>> current_year = timezone.now().year
>>> Question.objects.get(pub_date__year=current_year)
<Question: What's up?>
# 존재하지 않는 ID를 요청하면 예외가 발생합니다.
>>> Question.objects.get(id=2)
Traceback (most recent call last):
...
DoesNotExist: Question matching query does not exist.
# 기본 키로 조회하는 것이 가장 일반적인 경우이므로 Django는 기본 키 정확한 조회에 대한 단축키를 제공합니다.
# 다음은 Question.objects.get(id=1)과 동일합니다.
>>> Question.objects.get(pk=1)
<Question: What's up?>
# 사용자 정의 방법이 제대로 작동하는지 확인하십시오.
>>> q = Question.objects.get(pk=1)
>>> q.was_published_recently()
True
# 질문에 몇 가지 선택 사항을 제공합니다. create 호출은 새로운 Choice 객체를 생성하고,
# INSERT 문을 수행하고, 사용 가능한 선택 항목 집합에 선택 항목을 추가하고
# 새로운 Choice 객체를 반환합니다. Django 생성 ForeignKey 관계의 "다른 쪽"을 유지하기 위한 집합
# (예: 질문의 선택) API를 통해 액세스할 수 있습니다.
>>> q = Question.objects.get(pk=1)
# 관련 개체 집합에서 선택 항목을 표시합니다. 지금까지는 없습니다.
>>> q.choice_set.all()
<QuerySet []>
# 세 가지 선택지를 만듭니다.
>>> q.choice_set.create(choice_text='Not much', votes=0)
<Choice: Not much>
>>> q.choice_set.create(choice_text='The sky', votes=0)
<Choice: The sky>
>>> c = q.choice_set.create(choice_text='Just hacking again', votes=0)
# Choice 객체는 관련된 Question 객체에 대한 API 액세스 권한을 가집니다.
>>> c.question
<Question: What's up?>
# 그 반대의 경우도 마찬가지입니다. Question 객체는 Choice 객체에 액세스할 수 있습니다.
>>> q.choice_set.all()
<QuerySet [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]>
>>> q.choice_set.count()
3
# API는 필요한 만큼 관계를 자동으로 따릅니다. 관계를 구분하려면 이중 밑줄을 사용합니다.
# 원하는 만큼 깊이 있게 작동합니다. 제한이 없습니다.
# pub_date가 올해인 모든 질문에 대한 모든 선택 항목을 찾으십시오
# (위에서 만든 'current_year' 변수 재사용).
>>> Choice.objects.filter(question__pub_date__year=current_year)
<QuerySet [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]>
# 선택 항목 중 하나를 삭제합시다. 이를 위해 delete()를 사용하십시오.
>>> c = q.choice_set.filter(choice_text__startswith='Just hacking')
>>> c.delete()
💡 관리자 생성하기
관리 사이트에 로그인할 수 있는 사용자를 생성하기 위해 우선 아래와 같은 명령어를 입력한다.
py manage.py createsuperuser
원하는 username을 입력하고 엔터를 누르세요
Username: admin
그런 다음, 원하는 이메일 주소를 입력하라는 메시지가 표시됩니다.
Email address: admin@example.com
마지막으로, 암호를 입력한다. 암호를 두 번 물어보게 되는데, 두 번째 입력하는 암호를 올바로 입력했는지를 확인하기 위한 암호입니다.
Password: **********
Password (again): *********
Superuser created successfully.
💡 서버 개발 시작
Django 관리자 사이트는 기본적으로 활성화되어 있다. 개발 서버를 사용하기 위해서 아래 명령어를 입력해주면 개발 서버로 넘어가게 된다. 또는 로컬 도메인의 뒤에 "/admin" 입력해 주어도 된다
py manage.py runserver
💡 관리 사이트에서 poll app을 변경 가능하도록 만들기
polls/admin.py 파일을 열어 아래와 같이 수정
from django.contrib import admin
from .models import Question
admin.site.register(Question)
'BackEnd > Django, DRF' 카테고리의 다른 글
[Django] 프로젝트 구조 설정, 만드는 순서 (0) | 2022.11.22 |
---|---|
[Django] static 파일 이미지 HTML에 추가하기 (0) | 2022.11.20 |
[Django] 첫 번째 장고 앱 작성하기, part4 (0) | 2022.11.17 |
[Django] 첫 번째 장고 앱 작성하기, part3 (0) | 2022.11.15 |
[Django] 첫 번째 장고 앱 작성하기, part1 (0) | 2022.11.14 |