❗️ django tutorial를 보고 실습 내용을 정리한 글입니다.
잘못된 부분이 있다면 알려주세요 🙏
python version: 3.8.5
django version: 3.2
python 버전에 따른 django 버전
python -m pip install Django # django 설치 python -m django --version # django 버전 확인
django-admin startproject <APP 이름>
장고에서 프로젝트란 데이터베이스 구성, Django
관련 옵션 등 모든 설정을 포함하는 python 패키지를 의미한다. 이러한 일련의 과정을 위 코드 한 줄이면 자동으로 해준다.
아래는 startproject
명령어를 통해 생성된 파일(또는 폴더)이다.
APP Name/
manage.py
mysite/
__init__.py
settings.py
urls.py
asgi.py
wsgi.py
DJANGO_SETTINGS_MODULE
을 사용하여 settings.py
파일을 가르킨다.mysite.urls
처럼 사용해야한다.mysite
라는 디렉토리가 python 패키지라는 것을 python에게 알려주는 빈 파일.INSTALLED_APPS
를 보면 장고에서 미리 만들어 둔 앱들의 목록을 볼 수 있다. 여기엔 관리용 사이트, 인증 시스템, 세션 프레임워크, 메세징 프레임워크 등이 잇다.python manage.py runserver
위 명령어를 수행되면 장고 프로젝트 서버가 실행된다. http://127.0.0.1:8000/ 로 접속하면 아래와 같은 화면을 볼 수 있다.
python manage.py runserver 8080
기본적으로 8000
포트로 서버가 시작되나 위처럼 포트를 설정할 수도 있다. 또한 runserver
는 서버에 어떤 요청이 들어오면 자동으로 코드를 다시 실행하기 때문에 변경 사항을 적용하기 위해 서버를 재가동 할 필요는 없다. 다만, 파일 추가 같은 몇 가지의 경우에는 서버 재가동이 필요하다.
python manage.py startapp polls
프로젝트를 진행할 앱을 생성한다. 여기서는 polls
라는 앱을 생성했다. 그럼 아래처럼 polls
라는 디렉토리가 생성된다.
polls/
__init__.py
admin.py
apps.py
migrations/
__init__.py
models.py
tests.py
views.py
# polls/view.py
from django.http import HttpResponse
def index(request):
return HttpResponse("Hello, world. You're at the polls index.")
장고에서 가장 간단한 형태의 뷰이다. 이렇게 생성된 뷰를 호출하려면 url
이 있어야 한다. 그러기 위해 urls.py
를 생성해준다. 참고로 장고에서는 이러한 url
를 관리하는 파일을 urlConf
라고 부른다.
# polls/urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.index, name='index'),
]
최상위 url 관리 파일인 mysite/urls.py
에서 금방 만든 polls/urls.py
를 알려줘야한다.
mysite / urls.py ¶
from django.contrib import admin
from django.urls import include, path # include 추가
urlpatterns = [
path('polls/', include('polls.urls')), # polls/urls.py 등록
path('admin/', admin.site.urls),
]
include
함수는 polls/urls.py
과 같은 다른 url 패턴
를 참조할 수 있도록 도와주는 역할을 한다.
python manage.py runserver
이제 다시 서버를 실행하여 뷰를 확인해보자. http://localhost:8000/polls/ 여기에 접속하면 아래와 같이 정상적인 뷰를 확인할 수 있다.
장고는 기본적으로 SQLite
를 사용하도록 구성되어 있어 별도의 설치가 필요하지 않다. 다른 데이터베이스를 사용하고 싶다면 여기를 살펴보면 된다.
TIME_ZONE = 'Asia/Seoul' USE_TZ = False
가장 먼저 최상위/settings.py
에 TIME_ZONE
의 값을 위처럼 설정해 시간을 맞춘다. USE_TZ
가 False
여야 장고의 모든 시간대가 TIME_ZONE
에 설정한 시간으로 저장된다. 만약 True
면 템플릿이나 폼에서만 TIME_ZONE
에 설정한 시간으로 보여준다.
python manage.py migrate
migrate
명령은 settings.py
에 INSTALLED_APPS
의 설정을 확인하고 관련 앱들이 필요로 하는 데이터베이스 테이블을 만들어준다. INSTALLED_APPS
에는 아래와 같은 앱들이 미리 만들어져있는데, 보통 이러한 앱들은 최소 하나 이상의 데이터베이스 테이블을 필요로 하기때문에 아래와 같은 앱을 사용하기 전에 위 명령어를 수행해줘야한다.
만약 이러한 앱들 중 필요없는 앱이 있다면 주석처리를 하면 된다.
데이터베이스에서 모델이란 부가적인 메타데이터를 가진 데이터베이스의 구조(layout)을 말한다. 장고는 DRY(Don't repeat yourself) 원칙을 따르기 때문에 데이터 모델을 한 곳에 정의한다.
우리가 만들 앱에서는 두 가지 모델, Question
와 Choice
가 필요하다. Question
에서는 질문과 게시 날짜가 필요하고, 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')
class Choice(models.Model):
question = models.ForeignKey(Question, on_delete=models.CASCADE)
choice_text = models.CharField(max_length=200)
votes = models.IntegerField(default=0)
Question
과 Choice
라는 모델 두 개가 만들어졌다. 클래스 밑에 변수들은 데이터베이스의 필드로 CharField
는 문자 필드를 표현하고, DateTimeField
필드는 날짜와 시간 필드를 표현한다. 즉, 장고에게 각 필드가 어떤 데이터 타입이 필요한지 알려준다. 이런 필드명은 파이썬 코드에서 사용할 수 있다.
ForeignKey
는 외래키를 장고에게 알려주며 Choice
가 Question
에 관계가 된다는 것을 의미한다. Choice
의 question
변수가 Question
테이블 전체를 가리키고 있으니 1:N
관계이다.
굉장히 짧은 코드이지만 다양한 정보를 장고에게 알려준다. 데이터베이스 스키마를 생성(create table문)하고, Question
과 Choice
객체에 접근하기 위한 python 데이터베이스 접근 api를 생성한다.
현재 프로젝트에 앞서 만들었던 앱인 polls
앱이 설치되어 있다는 것을 알리기 위해 INSTALLED_APPS
에 해당 앱을 추가해야한다. 장고에서는 앞서 설명한대로 앱을 사용하기위해 꼭 이 곳에 앱을 명시해야한다.
polls/apps.py
를 보면 앱의 메타 데이터를 저장하는 PollsConfig
클래스가 존재한다. 이 PollsConfig
를 mysite/settings.py
의 INSTALLED_APPS
에 추가하면 장고는 polls
앱이 포함된 것을 알게 된다.
# mysite/settings.py
INSTALLED_APPS = [
'polls.apps.PollsConfig', # polls/apps.py안의 PollsConfig 클래스
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
python manage.py makemigrations polls
위 명령어를 통해 새로운 모델을 생성하거나 변경시킨 사실을 migration
에 저장하고 싶다는 것을 장고에게 알린다. polls
앱 아래의 migration
폴더에 앞서 생성한 모델를 생성하는 실제 코드 파일이 생성된다. 파일명은 0001_initial.py
로 저장된다. 여기서 migration
이란, 장고가 모델에 대한 변경사항을 저장하는 방법이다.
Migrations for 'polls':
polls/migrations/0001_initial.py
- Create model Question
- Create model Choice
명령어를 실행하면 위처럼 0001_initial.py
이라는 migration
파일이 생성되고 그 안에 앞서 만들었던 Question
과 Choice
모델의 정보가 적혀있다. 간단한 마이그레이션 파일이 실제로 어떤 SQL 문장을 실행하여 내부적으로 이와 같은 일을 하는지 살펴보기 위해 아래와 같은 명령어를 사용하면 된다. sqlmigrate
명령어는 migration
이름을 인수로 받아, 실행하는 SQL 문장을 보여준다. 다만, 실제로 migration
이 실행되는 것은 아니니 실제로 실행하려면 뒤에서 설명할 migrate
명령어를 실행해야한다.
python manage.py sqlmigrate polls 0001
BEGIN;
--
-- Create model Question
--
CREATE TABLE "polls_question" (
"id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,
"question_text" varchar(200) NOT NULL,
"pub_date" datetime NOT NULL);
--
-- Create model Choice
--
CREATE TABLE "polls_choice" (
"id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,
"choice_text" varchar(200) NOT NULL,
"votes" integer NOT NULL,
"question_id" bigint NOT NULL REFERENCES "polls_question" ("id") DEFERRABLE INITIALLY DEFERRED
);
CREATE INDEX "polls_choice_question_id_c5b4b260" ON "polls_choice" ("question_id");
COMMIT;
사용하는 데이터베이스에 따라 결과는 다르게 보이는데 위는 sqlite
이다.
테이블 이름은 앱의 이름과 모델의 이름(소문자)가 조합되어 자동으로 생성된다. 위 경우에는 앱의 이름인 polls
와 모델의 이름인 question
, choice
가 합쳐진것이다. 또한 기본 키인 ID
가 자동으로 주어지고, 외래키도 필드명에 _id
가 붙어 자동으로 추가된다. 테이블 이름, 기본 키, 외래키 모두 재지정이 가능하다.
이제 migrate
를 실행시켜 데이터베이스에 모델과 테이블을 생성할 것이다.
python manage.py migrate
migrate
는 아직 적용되지 않은 마이그레이션을 모두 수집해 실행하며 변경 사항들과 데이터베이스의 스키마의 동기화를 이룬다. 그렇기때문에 장고는 django_migrations
라는 테이블을 따로 만들어 마이그레이션 적용 여부를 추적한다.
python manage.py shell
파이썬 쉘을 실행하는 명령어이다. 이제 자유롭게 쿼리문을 사용하면 된다. 쿼리문에 대한 정보는 여기에 있다.
from polls.models import Choice, Question # Import the model classes we just wrote.
# 아직 Question에 아무것도 없음
Question.objects.all() # <QuerySet []>
# Question에 데이터 삽입
from django.utils import timezone
q = Question(question_text="What's new?", pub_date=timezone.now())
# save를 해야 변경사항이 저장됨.
q.save()
# 테이블 데이터 확인
q.id # 1
q.question_text # "What's new?"
q.pub_date # datetime.datetime(2021, 5, 12, 6, 14, 6, 457837, tzinfo=<UTC>)
# 데이터 변경
q.question_text = "What's up?"
q.save()
q.question_text # "What's up?"
# 데이터베이스의 Question 테이블의 모든 오브젝트 출력
Question.objects.all() # <QuerySet [<Question: Question object (1)>]>
데이터를 삽입하고 변경하는 등을 할 수 있다. 다만, 모든 오브젝트를 보기 위해 Question.objects.all()
명령어를 사용했는데 결과 값이 마음에 안 든다. 우리가 원하는 데이터의 값을 보여주도록 바꿀 수 있다.
# polls/models.py
from django.db import models
class Question(models.Model):
# ...
def __str__(self):
return self.question_text
class Choice(models.Model):
# ...
def __str__(self):
return self.choice_text
__str__()
메소드를 추가하면 프롬프트에서 편하게 데이터를 볼 수 있다. 또한 장고가 자동으로 생성하는 관리 사이트에서도 객체가 제대로 표시된다. 참고로 이렇게 코드를 수정하면 쉘을 종료했다가 다시 실행해야한다.
Question.objects.all() # <QuerySet [<Question: What's up?>]>
# polls/models.py
import datetime
from django.db import models
from django.utils import timezone
class Question(models.Model):
# ...
def was_published_recently(self):
return self.pub_date >= timezone.now() - datetime.timedelta(days=1)
생성일이 최근인지 아닌지 체크하는 메소드도 추가하였다. days=1
를 하여 최근 하루동안 생성한 데이터인지 확인하는 메소드이다.
q.was_published_recently() # True
다시 쉘을 사용해보자.
from polls.models import Choice, Question
Question.objects.filter(id=1) # <QuerySet [<Question: What's up?>]>
Question.objects.filter(question_text__startswith='What') # <QuerySet [<Question: What's up?>]>
# primary-key를 이용하여 데이터를 선택할 수 있다.
#여기서는 첫번째 primary-key 즉, id=1를 의미.
Question.objects.get(pk=1)
# Question의 pk가 1인 데이터와 연결된 Choice 테이블에 데이터를 추가한다.
q = Question.objects.get(pk=1)
q.choice_set.all() # <QuerySet []>
q.choice_set.create(choice_text='Not much', votes=0) # <Choice: Not much>
c = q.choice_set.create(choice_text='Just hacking again', votes=0)
c.question # <Question: What's up?>
# Choice 데이터 삭제
c.delete()
관리자 페이시를 사용하려면 관리자의 아이디와 패스워드가 필요하다.
python manage.py createsuperuser >>> Username: admin >>> Email address: admin@example.com >>> Pwd: ********** >>> Pwd (again): ********* >>> Superuser created successfully.
기본적으로 영어로 설정되어있지만, 설정 언어를 바꾸고 싶다면 settings.py
의 LANGUAGE_CODE
부분을 바꾸면 된다. 한국은 ko-KR
이고, 다른 나라도 여기서 찾을 수 있다.
앞서 생성한 관리자 아이디로 로그인을 하면 정상적으로 관리자 페이지에 진입할 수 있다.
이런 관리자 페이지는 장고에서 만든 인증 프레임 워크로 앞쪽에서 살펴봤던 INSTALLED_APPS
에 django.contrib.auth
모듈을 통해 제공된다.
관리자 페이지에는 poll
앱이 존재하지 않는다. 관리자가 Question
객체가 있다는 사실을 몰라서인데, 이를 관리자에게 알리기위해 polls/admin.py
를 아래와 같이 편집해야한다.
# polls/admin.py
from django.contrib import admin
from .models import Question
admin.site.register(Question)
Question
을 등록했으니 장고가 이를 통해 관리자 페이지에 앱을 표시한다.
Question
을 선택해 들어가면 데이터베이스 Question
테이블에 생성했던 질문들을 볼 수 있다.
질문 하나를 선택해서 들어가면, 수정 또는 삭제가 가능하다. 또한 테이블의 DateTimeField
필드는 자바스크립트로 표현된 달력 팝업과 함께 제공된다.
데이터를 변경하고 상단 우측에 있는 히스토리를 누르면 누가 언제 무엇을 바꾸었는지 확인 가능하다.