Django tutorial part 2

ryan·2020년 8월 29일
0

Django

목록 보기
4/4

Django tutorial part 2는 Django tutorial part 1 다음 부분이에요. Part 2에서는 데이터베이스를 설정하고, 첫 번째 Model을 만들고, Django의 자동 생성 관리 사이트에 대한 간략한 소개를 받을 거랍니다.

🖥 Database setup(데이터베이스 설정)

자, oursite/settings.py 파일을 여세요. 이 파일은 Django 설정을 나타내는 모듈 변수가 있는 일반적인 Python 모듈입니다.

기본적으로 configuration은 가장 쉬운 선택으로 SQLite를 사용해요. SQLite는 파이썬에 포함되어있어서 데이터베이스를 지원하기 위해서 다른 것을 설치할 필요가 없답니다. 참 좋죠? 하지만, 실질적인 첫 프로젝트를 시작하면 PostgreSQL 같은 확장 가능한 데이터베이스를 사용해서 향후 데이터베이스 전환 문제를 피하고 싶어할 수도 있어요.

다른 데이터베이스를 쓰고 싶으면, 여기를 참고해서 설치하세요.

튜토리얼에서는 SQLite를 사용할 거예요.

oursite/settings.py를 수정할 때, 우리가 있는 시간대로 TIME_ZONE을 설정하도록 해요.

또한, 파일 맨 위에 있는 INSTALLED_APPS 설정에 유의하세요. INSTALLED_APPS 설정은 이 Django instance에서 활성화 된 모든 Django 애플리케이션의 이름을 보유하고 있어요. 앱은 여러 프로젝트에서 사용할 수 있고, 다른 프로젝트에서 사용할 수 있도록 해키지화하고 배포 할 수 있답니다.

❓ 인스턴스(instance)

  • 인스턴스는 일반적으로 실행 중인 임의의 프로세스, 클래스의 현재 생성된 오브젝트를 가리킨다.
  • 객체(오브젝트)의 인스턴스는 데이터베이스나 SGA, 백그라운드 프로세스등 광범위한 컴퓨터시스템 자원의 접근에 할당된 물리 메모리의 일부를 가리킨다.
  • 종종 컴퓨터나 수학등에서 인스턴스는 사전적의미로서 일반적인 경우에대한 실제적인 특정 상황으로 실현된 경우이다. 즉 실질적 예이다. - wikipedia

기본적으로 INSTALLED_APPS에는 Django와 함께 제공되는 다음 앱들이 포함되어 있습니다.

  • django.contrib.admin – 관리 사이트. 곧, 사용할거에요. '와~ 신난다.'
  • django.contrib.auth – 인증 시스템
  • django.contrib.contenttypes – 컨텐츠 유형에 대한 프레임워크
  • django.contrib.sessions – 세션 프레임워크
  • django.contrib.messages – 메세징 프레임워크
  • django.contrib.staticfiles – 정적 파일들을 관리하는 프레임워크

이런 애플리케이션들은 일반적인 경우에 대해 편의를 위해서 기본적으로 포함돼요.

이러한 애플리케이션 중에 일부는 적어도 하나의 데이터베이스 테이블을 사용해야되서 사용하기 전에 테이터베이스에 테이블을 만들어줘야해요. 테이블을 만들기위해서, 다음 command를 입력하세요.

$ python manage.py migrate

migrate command은 INSTALLED_APPS 설정을 확인하고, oursite/settings.py 파일의 데이터베이스 설정 및 앱과 함께 제공되는 데이터베이스 migrations에 따라 필요한 데이터베이스 테이블을 만들어요.(이 부분은 나중에 다룰 거예요)

적용되는 각 migration에 대해서 메시지를 볼 수 있을 거예요. 호기심이 좀 생겼다면 데이터베이스에 대한 command-line client를 실행해보고, Django가 생성 한 테이블을 표시하기 위해서 .schema(SQLite)를 입력해보세요.

❓ .schema를 어떻게 사용하는 지 모르겠네요. 나중에 알아볼게요.

💃 모델 생성(Creating models)

자, 이제 models를 정의해볼게요. 음, 기본적으로 추가적인 메타데이터로 데이터베이스 레이아웃을 손 볼거예요.

우리가 만든 설문 조사 앱에서 Question과 Choice, 이 두 가지 model을 만들도록 해보죠. Question에는 질문과 게시 날짜가 있을 거고, Choice에는 선택하는 문구와 투표 집계(tally), 이 두 필드가 있을 거예요. 각 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)


여기에서 각 model은 django.db.models.Model을 하위클래스로 만드는 클래스로 표현돼요. 각 model은 많은 클래스 변수를 가지고 있어요. 각 클래스 변수는 데이터베이스 필드를 나타내요.

각 필드는 Field 클래스의 instance로 표현돼요. 예를 들어서, 문자 필드에 대해서는 CharField, 날짜시간에 대해서는 DateTimeField를 사용한답니다. 이 클래스들이 각 필드가 어떤 유형의 데이터를 가지고 있는지 Django에 알려주는 역할을 해요.

각 필드 instance(예시, question_text, pub_date)의 이름은 기계 친화적인 형식의 필드의 이름이예요. 파이썬 코드에 이 값을 사용할 거고, 데이터베이스에서 열 이름으로 사용할 거랍니다.

몇몇의 Field 클래스들은 필수 인자를 가지고 있기도 해요. 예를 들어서, CharField에는 'max_length'가 주어져야만하죠. 이러한 것들은 데이터베이스 schema에도 사용되고, 유효성 검사에도 사용됩니다.

필드는 또한 다양한 선택적인 인자를 가질 수 있어요. 튜토리얼에서는 투표의 기본 값을 0으로 설정했습니다.

마지막으로 ForeignKey를 사용하면서 관계가 정의됩니다. ForeignKey는 Django에게 각 Choice가 단일 Question과 관련되어 있다는 것을 알려줘요. Django는 다 대 일(many-to-one), 다 대 다(many-to-many), 일대일(one-to-one) 등 모든 공통 데이터 베이스 관계를 지원해요.

💪 모델 활성화(Activating models)

작지만 강한 저 모델 코드는 Django에게 아주 많은 정보를 줘요. 모델과 함께 Django가 할 수 있는 게 뭐가 있냐면:

  • 앱에 대한 데이터베이스 스키마(CREATE TABLE statements)를 만들 수 있다.
  • Question과 Choice 객체들에 접근하기위한 파이썬 데이터베이스 액세스 API를 만들 수 있다.

그 전에, 먼저 해야될 것이 있어요.
바로, 바로, 우리의 프로젝트에 polls 앱이 설치되었다는 것을 알려주는 거죠.

✋ 잠깐만~

Django 앱은 'pluggable'해요. 이 말은 즉, 여러 프로젝트에서 앱을 사용할 수 있고, 앱이 지정된 Django 설치에 연결될 필요가 없기 때문에 배포할 수 있다는 것을 의미해요.

다시, 본론으로 돌아와서
프로젝트에 앱을 포함하려면 INSTALLED_APPS 설정에서 configuration class에 대한 참조를 추가할 필요가 있어요. PollsConfig class는 polls/apps.py 파일이 있어요. 그래서 점선 경로는 'polls.apps.PollsConfig'가 됩니다. oursite/setting.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',
]


자, 이제 Django는 polls 앱을 포함하는 것을 알고 있어요. 이제 다른 command를 실행시켜볼게요.

$ python manage.py makemigrations polls

실행을 잘했다면 다음과 같은 문구들을 봐야만합니다.

Migrations for 'polls':
  polls/migrations/0001_initial.py
    - Create model Question
    - Create model Choice


makemigrations를 실행하면 models에 몇몇의 변경 사항이 있었다는 것(방금 한 것은 새 모델을 만들었다는 것)과 변경 사항을 migration으로 저장하고 싶다고 Django에게 말해주는 거랍니다. 무슨 말이죠 이게?

Migrations은 Django가 models(즉, 데이터베이스 스키마)에 변경 사항들을 저장하는 방법이고, 디스크 파일이라고 볼 수 있어요.

자동화로 데이터베이스 스키마를 관리하고 migratons를 실행하는 명령어가 있는데 'migrate'이라는 명령어에요. 조금 있다가 'migrate'을 다루도록 할게요. 그 전에, 먼저 migration이 실행되는 SQL을 보도록 할게요. sqlmigrate 명령어는 migration을 가져와서 해당 SQL을 반환해요.

$ python manage.py sqlmigrate polls 0001

위와 같이 입력하면 다음과 비슷한 내용을 볼 수 있어요.(텍스트는 가독성을 위해서 정리했다네요)

BEGIN;
--
-- Create model Question
--
CREATE TABLE "polls_question" (
    "id" serial NOT NULL PRIMARY KEY,
    "question_text" varchar(200) NOT NULL,
    "pub_date" timestamp with time zone NOT NULL
);
--
-- Create model Choice
--
CREATE TABLE "polls_choice" (
    "id" serial NOT NULL PRIMARY KEY,
    "choice_text" varchar(200) NOT NULL,
    "votes" integer NOT NULL,
    "question_id" integer NOT NULL
);
ALTER TABLE "polls_choice"
  ADD CONSTRAINT "polls_choice_question_id_c5b4b260_fk_polls_question_id"
    FOREIGN KEY ("question_id")
    REFERENCES "polls_question" ("id")
    DEFERRABLE INITIALLY DEFERRED;
CREATE INDEX "polls_choice_question_id_c5b4b260" ON "polls_choice" ("question_id");

COMMIT;

다음 사항들에 유의하세요:

  • 출력되는 내용은 사용하는 데이터베이스에 따라서 다를 수 있어요.
  • TABLE 이름은 앱 이름(polls)과 모델의 소문자 이름(question, choice)을 결합해서 자동으로 생성돼요. (다시 정의하는 것 가능)
  • 기본 키(ID)는 자동으로 추가돼요.(다시 정의하는 것 가능)
  • 관례 상(By convention), Django는 외부의 키 필드 이름에 "_id"를 추가해요. (네, 다시 정의하는 것 가능)
  • 외부 키 관계는 FOREIGN KEY 제약 조건에 따라서 명시돼요.
  • 사용 중인 데이터베이스에 맞게 조정되기때문에 MySQL, PostgreSQL, SQLite 등 데이터베이스별 필드 유형이 자동으로 처리왜요. 현재 우리가 사용하는 SQLite는 integer primary key autoincrement.
  • sqlmigrate 명령어는 사실 데이터베이스에 migration을 실행하지는 않아요. 대신에, SQL Django가 필요하다고 생각하는 것을 볼 수 있도록 화면에 출력해주죠. Django가 수행 할 작업을 확인하거나 변경을 위해서 SQL 스크립트가 필요한 데이터베이스 관리자가 있는 경우에 유용해요.

조금 더 흥미가 생겼다면, python manage.py check를 실행해보세요. 이 멸령어는 migration이나 database를 건들지않고, 프로젝트에 있는 문제를 확인해요.

자, 이제 migrate을 실행해서 데이터베이스에 모델 테이블을 만들어볼게요.

$ python manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, polls, sessions
Running migrations:
  Rendering model states... DONE
  Applying polls.0001_initial... OK


migrate 명령어는 적용되지않은 모든 migration을 가져와요.(Django는 django_migrations라는 데이터베이스의 특수 테이블을 사용해서 적용되는 migration을 추적한답니다.) 그리고 데이터베이스 대해서 실행을하죠. 기본적으로 모델의 변경 사항을 데이터베이스의 스키마와 동기화(synchronizing)시킵니다.

migration은 아주 강력하고 새로운 것을 생성하거나, 데이터베이스, 테이블을 지울 필요 없이 프로젝트를 개발할 때 시간이 지남에 따라서 모델을 바꿀 수 있게 해줍니다.

Model을 만드는데 지금까지했던 세 단계를 꼭 기억하도록해요.

  • Models 바꾸기(models.py 안에서)
  • python manage.py makemigrations을 실행해서 이러한 변경 사항에 대한 migrations을 만들기
  • python manage.py migrate을 실행해서 해당 변경 사항을 데이터베이스에 적용시키기

migration을 만들고 적용하는 별도의 명령이 있는 이유는 버전 관리 시스템으로 migration을 커밋하고 앱과 함께 제공하기 때문이에요. 이렇게하면 개발을 더 쉽게 할 수도 있꼬 다른 개발자와 production에서도 사용할 수 있어요.

manage.py 유틸리티가 할 수 있는 것에 대해서 더 자세히 알고 싶다면 여기를 참고하세요.

🤾‍ API 다루기

자, 이제 Interative 파이썬 shell로 이동해서 Django가 제공하는 무료 API를 사용해보도록하죠. 파이썬 shell을 호출하려면 다음 command를 사용합니다.

$ python manage.py shell


단순히 'python'을 입력하는 대신에 위 command를 사용해요. 왜냐하면 manage.py는 Django에 mysite/settings.py 파일에 대한 Python import path를 제공하는 DJANGO_SETTINGS_MODULE 환경 변수를 설정하기 때문이죠.

shell에 들어가면, 데이터베이스 API를 탐색해볼게요.

>>> from polls.models import Choice, Question  # 방금 우리가 작성한 model classes를 가져옵니다.

# 시스템에는 아직 아무런 질문이 있지 않아요.
>>> Question.objects.all()
<QuerySet []>

# 새로운 질문을 만드세요.
# 시간대 지원은 기본 설정 파일에서 활성화되어 있어서,
# Django pub_date에 있는 datetime을 예상해요. Use timezone.now()
# datetime.datetime.now() 대신에 timezone.now()를 사용하는 것이 올바릅니다.
>>> from django.utils import timezone
>>> q = Question(question_text="What's new?", pub_date=timezone.now())

# 객체를 데이터베이스 안에 저장하세요. save()를 명시적으로 호출해야해요.
>>> q.save()

# 이제 ID가 있어요.
>>> q.id
1

# Python attributes를 통해서 model field 값에 액세스하세요.
>>> q.question_text
"What's new?"
>>> q.pub_date
datetime.datetime(2012, 2, 26, 13, 0, 0, 775217, tzinfo=<UTC>)

# attributes를 변경한 다음 save()를 호출해서 값을 변경하세요.
>>> q.question_text = "What's up?"
>>> q.save()

# objects.all()은 데이터베이스의 모든 질문을 표시해요.
>>> Question.objects.all()
<QuerySet [<Question: Question object (1)>]>

웨이~러~미닛. <Question: Question object (1)>은 이 객체의 유용한 표현이 아니에요. polls/models.py 파일에 있는 Question model을 편집하고, Question과 Choice 모두에 str() 메서드를 추가해서 문제를 해결해볼게요.

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

models에 str() 메서드를 추가하는 것은 아주 중요합니다. interactive 프롬프트 처리할 때 편의를 위해서도 그렇고, Django의 자동 생성 관리자 전체에서 객체의 표현이 사용되기때문이죠.

자, 이 model에 커스텀 메서드를 추가해볼게요.

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)

django.utils.timezone에서 각각의 Python 표준 datetime 모듈과 Django의 시간대 관련 유틸리티를 참조하기 위해서 import datetime 및 from django.utils import timezone이 추가되었다는 것을 확인하세요. 파이썬의 time zone을 다루는데 익숙하지않다면, 여기를 보세요.

이 변경사항들을 저장하고, python manage.py shell을 다시 실행해서 새 python 대화 형 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.

# primary key로 조회하는 것이 가장 일반적인 경우에요.
# Django는 primary key의 정확한 조회를 위한 shortcut(지름길? 바로가기)를 제공해요. 
# 다음은 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

# 질문에 몇 가지 선택사항을 주세요. 생성 호출은 새 Choice 객체를 생성하고,
# Insert statement(문)을 수행하며 사용 가능한 choices의 집합을 추가하고,
# 새로운 Choice 객체를 반환해요.
# Django는 API를 통해 액세스 할 수 있는
# ForeignKey 관계(예시. 질문의 선택)의 '다른 쪽'을 보유하는 집합을 생성해요.
>>> 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 objects(객체)에 대한 API 액세스 권한이 있어요.
>>> c.question
<Question: What's up?>

# 그 반대도 마찬가지에요. 질문 개체는 Choice 객체에 액세스 할 수 있어요.
>>> q.choice_set.all()
<QuerySet [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]>
>>> q.choice_set.count()
3

# API는 필요로하는만큼 관계를 자동으로 따라가요.
# 관계를 구분하려면 이중 밑줄(__use__)을 사용하세요.
# 이것은 제한 없이 원하는만큼 깊이 작동해요.
# pub_date가 올해인 질문에 대한 모든 Choices를 찾으세요.
# (위에서 만든 'current_year' 변수를 재사용).
>>> Choice.objects.filter(question__pub_date__year=current_year)
<QuerySet [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]>

# Let's delete one of the choices. Use delete() for that.
# choices 중에 하나를 지우도록해봐요. delete()를 사용하세요.
>>> c = q.choice_set.filter(choice_text__startswith='Just hacking')
>>> c.delete()

model 관계에 대해서 더 자세히 알고 싶으면 여기를 확인하세요. 이중 밑줄(__)을 사용해서 API를 통해 필드 조회를 수행하는 방법에 대한 자세한 내용은 여기에서 확인하세요. 데이터베이스 API에 대한 자세한 내용은 여기를 참조하세요.

🍳 Django Admin 소개(관리 사이트)

  • Django는 model에 대한 관리 인터페이스 생성을 완전히 자동화해요.
  • Admin은 사이트 관리자를 위한 것으로 사이트 방문자가 사용할 수 없습니다.

🐓 admin user(관리자) 생성하기

자, 첫번 째로 해야하는 일은 관리 사이트에 로그인 할 수 있는 사용자를 만드는 거예요. 다음 command를 실행해보죠.

$ python manage.py createsuperuser

사용자 이름을 입력하세요

Username: admin

그러면 원하는 이메일 주소를 입력하라는 표시를 하게됩니다.

마지막 단계는 비밀번호를 입력하는 거예요. 

🐣 개발 서버 시작하기

Django 관리 사이트가 기본값을 활성화되었어요. 개발 서버를 시작하고, 탐색해보아요.

서버를 실행하려면 다음과 같이 입력하세요

$ python manage.py runserver

그리고 브라우저를 열고 로컬 도메인에 있는 "/admin/"로 접속하세요. 예, http://127.0.0.1:8000/admin/. 그러면 다음과 같은 관리자 로그인 화면이 볼 수 있을 거예요.

🐥 관리자 사이트 입력하기

아까 전에 입력한 username과 비밀번호로 로그인해보세요. 그럼 다음과 같은 Django admin index 페이지를 볼 수 있을 거예요.

몇 가지 유형의 편집 가능한 컨텐츠(groups and users)가 표시되어야해요. 이것들은 Django에서 제공하는 인증 프레임워크인 django.contrib.auth에서 제공해요.

🐔 관리자에서 설문 조사 앱을 수정 가능하게 만들기

어? 그런데 우리가 만든 설문 조사 앱은 어디에 있죠? 보이지가 않네요.
(보이지 않아 아직도~)

한 가지 할 일이 더 있어요. 관리자에게 Question 객체에 관리자 인터페이스가 있다는 것을 알려야하는 것이죠. 이걸 하기위해서는 polls/admin.py 파일을 열어서 아래와 같이 수정해줘야합니다.

from django.contrib import admin

from .models import Question

admin.site.register(Question)

🧇 무료 관리자 기능들을 살펴볼 시간입니다

자, Questions를 등록했어요. Django가 이게 admin index page에 보여야된다는 것을 잘 알고 있네요.

Questions를 클릭하세요. 이제 questions에 대한 'change list' 페이지에 있네요. 이 페이지가 데이터베이스에 있는 모든 질문들을 보여주고, 선택하면 바꿀 수 있도록 해줍니다. 일찍이 우리가 만들었던 "What's up?" 질문이 보이네요.

"What's up?" question을 누르고 바꿔봅시다. (바꿔~바꿔~바꿔~)

유의할 사랑이 몇 가지 있어요:

  • 양식은 Question model에서 자동으로 생성돼요.
  • 다른 모델 필드 유형 (DateTimeField, CharField)은 적절한 HTML input widget에 해당해요. 각 필드 요형은 Django 관리자에서 자신을 표시하는 방법을 알고 있어요.
  • 각 DateTimeField에는 무료 JavaScript 단축키가 제공돼요. 날짜에는 'Today' 바로 가기와 달력 팝업이 표시되고, 시간에는 'Now' 바로 가기와 자주 입력하는 시간을 나열하는 편리한 팝업이 표시된답니다.

페이지 하단에는 몇 가지 옵션도 있어요:

  • Save
  • Save and continue edting
  • Save and add another
  • Delete

"Today"와 "Now" 바로가기를 클릭해서 "Date published" 바꾸세요. 그리고 "Save and continue editing"을 클릭하세요. 그리고 상단 오른쪽에 있는 "History"를 클릭하세요. Django 관리자를 통해서 이 객체에 대한 모든 변경 사항을 나열한 페이지와 변경한 사람이 변경한 시간과 누가 변경했는지 표시됩니다.

profile
👨🏻‍💻☕️ 🎹🎵 🐰🎶 🛫📷

0개의 댓글