Django 사용해보기 - 1

Sawol·2021년 5월 12일
0

django

목록 보기
1/5
post-thumbnail

❗️ django tutorial를 보고 실습 내용을 정리한 글입니다.

잘못된 부분이 있다면 알려주세요 🙏

사용 환경

python version: 3.8.5
django version: 3.2
python 버전에 따른 django 버전

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
  • APP Name
    프로젝트 컨테이너. 이름은 중요하지 않고, 원하는 이름으로 언제든 바꿀 수 있다.
  • manage.py
    django에 필요한 명령 줄 유틸리티. DJANGO_SETTINGS_MODULE을 사용하여 settings.py 파일을 가르킨다.
  • mysite
    프로젝트의 실제 python 패키지이다. 즉, 안에 있는 파일들을 사용하려면 mysite.urls처럼 사용해야한다.
  • mysite/__init__.py
    mysite라는 디렉토리가 python 패키지라는 것을 python에게 알려주는 빈 파일.
  • mysite/settings.py
    현재 프로젝트의 환경 및 구성등을 저장한다. 또한 INSTALLED_APPS를 보면 장고에서 미리 만들어 둔 앱들의 목록을 볼 수 있다. 여기엔 관리용 사이트, 인증 시스템, 세션 프레임워크, 메세징 프레임워크 등이 잇다.
  • mysite/urls.py
    현재 프로젝트의 url을 저장한다.
  • mysite/asgi.py
    웹서버, 프레임워크, 애플리케이션을 연결해주는 역할을 한다.
  • mysite/wsgi.py
    위의 asgi.py의 하위 버전.

서버 시작

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.pyTIME_ZONE의 값을 위처럼 설정해 시간을 맞춘다. USE_TZFalse여야 장고의 모든 시간대가 TIME_ZONE에 설정한 시간으로 저장된다. 만약 True면 템플릿이나 폼에서만 TIME_ZONE에 설정한 시간으로 보여준다.

python manage.py migrate

migrate 명령은 settings.pyINSTALLED_APPS의 설정을 확인하고 관련 앱들이 필요로 하는 데이터베이스 테이블을 만들어준다. INSTALLED_APPS에는 아래와 같은 앱들이 미리 만들어져있는데, 보통 이러한 앱들은 최소 하나 이상의 데이터베이스 테이블을 필요로 하기때문에 아래와 같은 앱을 사용하기 전에 위 명령어를 수행해줘야한다.

  • django.contrib.admin – 관리용 사이트. 곧 사용하게 될 겁니다.
  • django.contrib.auth – 인증 시스템.
  • django.contrib.contenttypes – 컨텐츠 타입을 위한 프레임워크.
  • django.contrib.sessions – 세션 프레임워크.
  • django.contrib.messages – 메세징 프레임워크.
  • django.contrib.staticfiles – 정적 파일을 관리하는 프레임워크.

만약 이러한 앱들 중 필요없는 앱이 있다면 주석처리를 하면 된다.

모델 만들기

데이터베이스에서 모델이란 부가적인 메타데이터를 가진 데이터베이스의 구조(layout)을 말한다. 장고는 DRY(Don't repeat yourself) 원칙을 따르기 때문에 데이터 모델을 한 곳에 정의한다.
우리가 만들 앱에서는 두 가지 모델, QuestionChoice가 필요하다. 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)

QuestionChoice라는 모델 두 개가 만들어졌다. 클래스 밑에 변수들은 데이터베이스의 필드로 CharField는 문자 필드를 표현하고, DateTimeField 필드는 날짜와 시간 필드를 표현한다. 즉, 장고에게 각 필드가 어떤 데이터 타입이 필요한지 알려준다. 이런 필드명은 파이썬 코드에서 사용할 수 있다.
ForeignKey는 외래키를 장고에게 알려주며 ChoiceQuestion에 관계가 된다는 것을 의미한다. Choicequestion 변수가 Question 테이블 전체를 가리키고 있으니 1:N관계이다.
굉장히 짧은 코드이지만 다양한 정보를 장고에게 알려준다. 데이터베이스 스키마를 생성(create table문)하고, QuestionChoice 객체에 접근하기 위한 python 데이터베이스 접근 api를 생성한다.

현재 프로젝트에 앞서 만들었던 앱인 polls 앱이 설치되어 있다는 것을 알리기 위해 INSTALLED_APPS에 해당 앱을 추가해야한다. 장고에서는 앞서 설명한대로 앱을 사용하기위해 꼭 이 곳에 앱을 명시해야한다.
polls/apps.py를 보면 앱의 메타 데이터를 저장하는 PollsConfig 클래스가 존재한다. 이 PollsConfigmysite/settings.pyINSTALLED_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 파일이 생성되고 그 안에 앞서 만들었던 QuestionChoice 모델의 정보가 적혀있다. 간단한 마이그레이션 파일이 실제로 어떤 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라는 테이블을 따로 만들어 마이그레이션 적용 여부를 추적한다.

API를 이용해 데이터베이스 사용하기

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.pyLANGUAGE_CODE부분을 바꾸면 된다. 한국은 ko-KR이고, 다른 나라도 여기서 찾을 수 있다.

앞서 생성한 관리자 아이디로 로그인을 하면 정상적으로 관리자 페이지에 진입할 수 있다.

이런 관리자 페이지는 장고에서 만든 인증 프레임 워크로 앞쪽에서 살펴봤던 INSTALLED_APPSdjango.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필드는 자바스크립트로 표현된 달력 팝업과 함께 제공된다.

데이터를 변경하고 상단 우측에 있는 히스토리를 누르면 누가 언제 무엇을 바꾸었는지 확인 가능하다.

0개의 댓글