상세 컨텐츠

본문 제목

[파이썬 웹 프로그래밍] #2. 간단한 Project 시작

IT/Django

by HarimKang 2020. 6. 15. 18:01

본문

Writer: Harim Kang

간단한 Django APP 만들기

'파이썬 웹 프로그래밍(실전편)'을 공부하면서 정리한 글입니다. 책에서는 리눅스 환경에서 진행하지만 저는 윈도우 환경에서 실습을 따라가 보겠습니다. Windows 10 OS환경 이지만 해당 책을 공부하고 싶은 분들에게 도움을 드리고 싶습니다. 장고에 대한 기본적인 내용은 아래의 포스팅에서 확인할 수 있습니다.

Application Architecture Design

Django는 MVT 패턴 설계를 바탕으로 다른 sw와 마찬가지로 설계, 구현의 과정을 진행하면 됩니다.

UI Design

  • 화면 UI 설계입니다.
  • templates\ 의 *.html 파일에 UI들을 작성합니다.

Table Design

  • 테이블 설계는 model과 관련되어 있습니다.
  • models.py에 코딩합니다.

Logic Design

  • 흐름을 설계합니다.
  • URL을 받아서, HTML Template을 만드는 것이 하나의 로직입니다.
  • 로직 설계는 설계의 핵심으로, 문서로 표현하여야 합니다.

URL Design

  • URL 설계는 URLconf에 반영됩니다.
  • urls.py에 코딩합니다.
  • URL 패턴, View Name, Template file name과 view에서 사용되는 Generic View 정의

작업 순서

  1. Project 생성 & 설정- startproject / settings.py
  2. 테이블 생성 - migrate
  3. Project 관리자 생성 - createsuperuser
  4. App 생성 & 설정 - startapp / settings.py
  5. 테이블(model) 정의 & Admin site에 등록 - models.py / admin.py
  6. URL 정의 (URLconf 코딩) - urls.py
  7. View 로직 작성 - views.py
  8. Template 작성 - template/*.html

Implementation

Project 생성

(가상 환경) D:\dev\Source\django> django-admin startproject [프로젝트 이름]

'''
# tree 명령어 - 내부 구조를 쉽게 확인할 수 있습니다.
# https://docs.microsoft.com/ko-kr/windows-server/administration/windows-commands/tree
> tree D:\dev\Source\django\[프로젝트 이름] /f
D:\DEV\SOURCE\DJANGO\[프로젝트 이름]
│  manage.py
│
└─[프로젝트 이름]
        asgi.py
        settings.py
        urls.py
        wsgi.py
        __init__.py
'''
  • 위의 명령어로 프로젝트를 생성할 수 있고, tree 명령어를 통해 구조를 확인할 수 있습니다.

프로젝트 설정 (settings.py)

  • 이제 settings.py에서 프로젝트 설정을 해보겠습니다. 설정과 관련된 자세한 내용들은 아래의 코드에 주석으로 설명하였습니다.

      # settings.py의 일부 설정이 필요한 부분만을 가져왔습니다.
    
      # DEBUG 변수가 True일 때는 개발모드, False일 때는 운영 모드입니다.
      # DEBUG = False인 경우, ALLOWED_HOSTS에 서버의 IP or Domain을 지정해주어야합니다.
      # DEBUG = True일 때는, Default로 localhost가 지정됩니다.
      DEBUG = True
      ALLOWED_HOSTS = ['localhost', '127.0.0.1']
    
      # 프로젝트에서 사용하는 APP을 등록하는 부분입니다.
      # startapp을 통해서 APP을 생성하면 등록을 해야합니다.
      # 현재는 프로젝트 생성시, 기본으로 등록되는 APP들이 있습니다.
      INSTALLED_APPS = [
          'django.contrib.admin',
          'django.contrib.auth',
          'django.contrib.contenttypes',
          'django.contrib.sessions',
          'django.contrib.messages',
          'django.contrib.staticfiles',
      ]
    
      # Templates 설정은 아래의 DIRS 항목에 템플릿 위치를 추가합니다.
      TEMPLATES = [
          {
              'BACKEND': 'django.template.backends.django.DjangoTemplates',
              'DIRS': [os.path.join(BASE_DIR, 'templates')], # <- 해당 부분에 템플릿이 위치할 디렉토리를 지정합니다.
              'APP_DIRS': True,
              'OPTIONS': {
                  'context_processors': [
                      'django.template.context_processors.debug',
                      'django.template.context_processors.request',
                      'django.contrib.auth.context_processors.auth',
                      'django.contrib.messages.context_processors.messages',
                  ],
              },
          },
      ]
    
      # Database 엔진 설정입니다. Django의 Defalut DB는 SQLite3입니다.
      # MYSQL, Oracle, PostgreSQL 등의 DB로 변경할 수 있습니다.
      # https://docs.djangoproject.com/en/3.0/ref/settings/#databases
      DATABASES = {
          'default': {
              'ENGINE': 'django.db.backends.sqlite3',
              'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
          }
      }
    
      # 언어 및 Timezone 설정입니다.
      # LANGUAGE_CODE의 Default 값은 'en-us'로 되어있습니다. 한글은 'ko-kr'입니다.
      # TIME_ZONE의 Default 값은 세계표준시인 'UTC', 한국 시간은 'Asia/Seoul'입니다.
      LANGUAGE_CODE = 'en-us'
      TIME_ZONE = 'Asia/Seoul'
    
      # 정적 파일(CSS, JavaScript, Images)에 대한 설정입니다.
      # https://docs.djangoproject.com/en/3.0/howto/static-files/
      STATIC_URL = '/static/'
      STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')] # <- 추가
    
      # Media files에 대한 설정입니다. - 파일 업로드 기능과 관련
      MEDIA_URL = '/media/'
      MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

테이블(Model) 생성

  • migrate 명령어는 DB에 변경사항이 있을 때 이를 반영하는 명령어입니다.
  • Django에서는 사용자 및 그룹 테이블이 필수적인 요소입니다. 그래서 이를 미리 migrate 명령어를 통해 DB를 설정하고 관련 파일을 생성합니다.
(가상 환경) D:\dev\Source\django> python manage.py migrate
'''
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying admin.0001_initial... OK
  Applying admin.0002_logentry_remove_auto_add... OK
  Applying admin.0003_logentry_add_action_flag_choices... OK
  Applying contenttypes.0002_remove_content_type_name... OK
  Applying auth.0002_alter_permission_name_max_length... OK
  Applying auth.0003_alter_user_email_max_length... OK
  Applying auth.0004_alter_user_username_opts... OK
  Applying auth.0005_alter_user_last_login_null... OK
  Applying auth.0006_require_contenttypes_0002... OK
  Applying auth.0007_alter_validators_add_error_messages... OK
  Applying auth.0008_alter_user_username_max_length... OK
  Applying auth.0009_alter_user_last_name_max_length... OK
  Applying auth.0010_alter_group_name_max_length... OK
  Applying auth.0011_update_proxy_permissions... OK
  Applying sessions.0001_initial... OK
'''
  • 위의 명령어를 실행하면 결과로 db.sqlite3 파일이 생성됩니다.
(가상 환경) D:\dev\Source\django> tree D:\dev\Source\django\[프로젝트 이름] /f
'''
D:\DEV\SOURCE\DJANGO\[프로젝트 이름]
│  db.sqlite3
│  manage.py
│
└─bookmark
    │  asgi.py
    │  settings.py
    │  urls.py
    │  wsgi.py
    │  __init__.py
    │
    └─__pycache__
            settings.cpython-37.pyc
            urls.cpython-37.pyc
            __init__.cpython-37.pyc
'''

Super-user 생성

  • Admin 사이트에 접속하기 위해서는 관리자 계정이 필요합니다.
(가상 환경) D:\dev\Source\django\[프로젝트 이름]> python manage.py createsuperuser
'''
사용자 이름 (leave blank to use 'harim'):
이메일 주소: harimkang4422@gmail.com
Password: # <- 비밀번호 입력
Password (again): # <- 비밀번호 확인
Superuser created successfully.
'''
  • 위의 코드를 통해 관리자 계정을 생성합니다.

APP 생성

  • App을 만드는 명령어는 아래와 같이 startapp [app 이름]을 입력합니다.
(가상 환경) D:\dev\Source\django\[프로젝트 이름]> python manage.py startapp [app 이름]
  • 위의 명령어를 통해 아래와 같은 app 관련 파일들이 생성됩니다.
(가상 환경) D:\dev\Source\django\[프로젝트 이름]> tree D:\dev\Source\django\[프로젝트 이름]\[앱 이름] /f
'''
D:\DEV\SOURCE\DJANGO\[프로젝트 이름]\[앱 이름]
│  admin.py
│  apps.py
│  models.py
│  tests.py
│  views.py
│  __init__.py
│
└─migrations
        __init__.py
'''
  • App을 생성했으니 다시 settings.py에 app을 등록해주어야 합니다.
# [프로젝트 이름]\settings.py
# 등록할 이름은 해당 app 디렉토리의 
# app.py의 [앱 이름]Config 클래스를 확인하시면 됩니다.
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
        '[app 이름].apps.[app.py의 Config 클래스 이름]',
]

Model 정의

  • 테이블 정의는 책의 예제를 따라서 Bookmark 테이블 하나로 정의합니다.
  • models.py에 작성하면 됩니다.
# [앱 이름]\models.py
from django.db import models

# Create your models here.
class Bookmark(models.Model):
    title = models.CharField('TITLE', max_length=100, blank=True)
    url = models.URLField('URL', unique=True)

    def __str__(self):
        return self.title
  • 기본적으로 class하나 당 하나의 테이블이라고 생각하면 됩니다.
  • 각각의 내부 변수들은 테이블의 column에 mapping 됩니다.
  • 테이블 클래스는 django.db.models.Model을 상속받습니다.
  • 구성요소
    • title: models의 CharField 필드 클래스를 사용하여 Char 컬럼으로 선언합니다. 'TITLE'은 컬럼의 이름이며, max_length는 최대 크기, blank는 공백을 가질 수 있다는 의미입니다.
    • url: URLField 클래스를 사용합니다.
    • str: 객체를 문자열로 표현할 때 필요한 메소드입니다. 레코드 명을 보여주어야할 때 사용됩니다.
  • Admin 사이트에 테이블 반영을 위해서는 admin.py을 수정해주면 됩니다.
# [앱 디렉토리]\admin.py
from django.contrib import admin
from [앱 디렉토리].models import Bookmark

# Register your models here.
@admin.register(Bookmark)
class BookmarkAdmin(admin.ModelAdmin):
    list_display = ('id', 'title', url')
  • 위와 같이 model 정의 시에는, admin 파일도 함께 추가해주어야 합니다.

DB 변경 반영

  • 변경 사항을 DB에 반영해주어야 합니다.
  • 각 app들은 app별로 마이그레이션 정보를 관리합니다. makemigration [app]을 통해서 [app]/migrations 디렉토리를 생성합니다.
  • 각 app들의 migration 정보를 프로젝트에서 migrate 명령으로 DB에 반영합니다.
(가상 환경) D:\dev\Source\django\[프로젝트 이름]> python manage.py makemigrations [앱 이름]
'''
Migrations for '[앱 이름]':
  [앱 이름]\migrations\0001_initial.py
    - Create model Bookmark
'''
(가상 환경) D:\dev\Source\django\[프로젝트 이름]> python manage.py migrate
'''
Operations to perform:
  Apply all migrations: admin, auth, [app], contenttypes, sessions
Running migrations:
  Applying [app].0001_initial... OK
'''
  • migration 관련 주요 명령어들을 모아보면 아래와 같습니다.
# Project 수준의 migration --> DB에 반영
> python manage.py migrate

# APP 수준의 migration 준비 --> 프로젝트에 통합될 준비
> python manage.py makemigrations [app]

# 모든 migration을 보여주고, 적용 여부를 출력
> python manage.py showmigrations

# [app]의 [n]번 마이그레이션을 적용할 때 사용될 SQL 문장을 출력
> python manage.py sqlmigrate [app] [n]
  • 이제 반영된 모습을 확인해보겠습니다.

      # Django Server 실행 (Background) // 종료는 Ctrl+Break
      (가상 환경) D:\dev\Source\django\[프로젝트 이름]> python manage.py runserver 0.0.0.0:8000
      '''
      Watching for file changes with StatReloader
      Performing system checks...
    
      System check identified no issues (0 silenced).
      June 15, 2020 - 14:39:57
      Django version 3.0.6, using settings '[Project name].settings'
      Starting development server at http://0.0.0.0:8000/
      Quit the server with CTRL-BREAK.
      '''
    • 위의 명령어를 통해 서버를 실행할 수 있고, http://127.0.0.1:8000/admin 주소로 admin 사이트에 접속합니다.

    • 아까 생성한 관리자 계정으로 로그인합니다.

    • 이제 Bookmark의 옆 [추가]버튼을 누르면 아래와 같이 아까 설정한 변수들을 추가할 수 있게 화면이 나옵니다. 이를 통해 DB에 반영이 되었음을 확인 할 수 있습니다.

URLconf 구성

# [Projectname]\urls.py
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),

    # class-based views
    path('[appname]/', include('[appname].urls')),
]
  • 프로젝트 수준의 urls에서는 [appname]에 대한 urlpattern을 추가해줍니다.
# [appname]\urls.py
from django.urls import path
from .views import BookmarkLV, BookmarkDV

urlpatterns = [
    path('', BookmarkLV.as_view(), name='index'),
    path('<int:pk>/', BookmarkDV.as_view(), name='detail'),
]
  • 위의 코드는 app 수준의 url 패턴 정의로, [appname] 디렉토리 안에 urls.py를 생성해줍니다.
  • 여기서 import하는 BookmarkLV(List View)와 BookmarkDV(Detail View)는 view 클래스로서, 아직 해당 글 흐름에서는 선언하지 않았습니다.
  • path(): 첫 번째 인자는 route로, URL에서 사용될 주소입니다. 두 번째 인자는 주소로 요청이 들어왔을 대 처리하는 view 클래스입니다. name은 URL 패턴의 이름입니다.

View Class (views.py)

  • 이제는 BookmarkLV와 BookmarkDV라는 view 클래스를 만들어보겠습니다.

      # [appname]\views.py
      from django.shortcuts import render
    
      # class형 Generic View ListView, DetailView 사용
      from django.views.generic import ListView, DetailView
      # Table 조회를 위한 model class import
      from bm.models import Bookmark
    
      # Create your views here.
      class BookmarkLV(ListView):
          # Bookmark 테이블의 Record list를 보여주기 위한 View class
          # 객체가 담긴 List를 구성하여 Context 변수(object_list)로 Template에 전달하는 역할
          # Template file name: bm/bookmark_list.html
          model = Bookmark
    
      class BookmarkDV(DetailView):
          # Bookmark 테이블 특정 Record에 대한 meta-data를 보여주는 View Class
          # 특정 객체 하나를 Context 변수(object)에 담아 Template에 전달하는 역할
          # Template file name: bm/bookmark_detail.html
          model = Bookmark
    • BookmarkLV: Bookmark 테이블의 데이터를 보여주기 위한 뷰입니다.
    • BookmarkDV: Bookmark 테이블의 특정 데이터의 메타데이터를 보여주기 위한 뷰입니다.

Template (/template/)

# bookmark_list.html
<!DOCTYPE html>
<html>

<head>
<title>Harim Bookmark List</title>
</head>

<body>

<div id="content">

    <h1>Bookmark List</h1>
    <ul>
        {% for bookmark in object_list %}
            <li><a href="{% url 'detail' bookmark.id %}">{{ bookmark }}</a></li>
        {% endfor %}
    </ul>

</div>
</body>
</html>
  • 위의 html 파일은 BookmarkLV와 연결된 템플릿 파일입니다.

  • 안에- 형식으로 object_list의 데이터들을 리스트로 보여줍니다.

    • 를 통해 각 데이터에 해당되는 detail view url을 연결합니다.
    • {{bookmark}}와 아까 클래스에서 선언한 str이 연결되어 출력됩니다.
    # bookmark_detail.html
    <!DOCTYPE html>
    <html>
    
    <head>
    <title>Harim Bookmark Detail</title>
    </head>
    
    <body>
    
    <div id="content">
    
        <h1>{{ object.title }}</h1>
    
        <ul>
            <li>URL: <a href="{{ object.url }}">{{ object.url}}</a></li>
        </ul>
    
    </div>
    
    </body>
    
    </html>
    • 해당 파일은 BookmarkDV 클래스와 연결된 템플릿 파일입니다.
    • {{ object.url }}을 통해서 object의 url 변수에 접근합니다.

    결과 확인하기

    1. 서버 실행 > 다시 http://127.0.0.1:8000/admin로 접속 > bookmark [추가]

    2. 2개의 bookmark [저장]

    3. http://127.0.0.1:8000/bookmark 접속

    4. Naver [click]

Project의 최종 구성

D:\DEV\SOURCE\DJANGO\PROJECT
│  db.sqlite3
│  manage.py
│
├─.idea
│  │  bookmark.iml
│  │  misc.xml
│  │  modules.xml
│  │  workspace.xml
│  │
│  └─inspectionProfiles
│          profiles_settings.xml
│
├─bookmark
│  │  admin.py
│  │  apps.py
│  │  models.py
│  │  tests.py
│  │  urls.py
│  │  views.py
│  │  __init__.py
│  │
│  ├─migrations
│  │  │  0001_initial.py
│  │  │  __init__.py
│  │  │
│  │  └─__pycache__
│  │          0001_initial.cpython-37.pyc
│  │          __init__.cpython-37.pyc
│  │
│  ├─templates
│  │  └─bookmark
│  │          bookmark_detail.html
│  │          bookmark_list.html
│  │
│  └─__pycache__
│          admin.cpython-37.pyc
│          apps.cpython-37.pyc
│          models.cpython-37.pyc
│          urls.cpython-37.pyc
│          views.cpython-37.pyc
│          __init__.cpython-37.pyc
│
└─mypage
    │  asgi.py
    │  settings.py
    │  urls.py
    │  wsgi.py
    │  __init__.py
    │
    └─__pycache__
            settings.cpython-37.pyc
            urls.cpython-37.pyc
            wsgi.cpython-37.pyc
            __init__.cpython-37.pyc

 

'IT > Django' 카테고리의 다른 글

[파이썬 웹 프로그래밍] #1. 장고(Django) 란?  (0) 2020.05.19

관련글 더보기

댓글 영역