[프로그래머스인공지능스쿨]Web Application with Django

6 minute read

Make Website with django

django 시작하기

django?

  • Python 기반 웹 프레임워크
  • pinterest, instagrem이 django가 쓰인 대표적인 플랫폼이다.
    장고와 플라스크 모두 같은 프레임워크지만, 지향성이 조금 다르다.
    플라스크의 경우, “마이크로”라는 말이 항상 앞에 붙는다. 이 마이크로란, 최소한의 기능을 갖고 있다는 것이다. 따라서 여기에 살을 붙여가면서 빌드업을 하는 구조이다. 작은 프로젝트에 적합하다.
    반면 장고의 경우, 이미 거의 모든 것이 내장되어있는 구조로 되어있다. 따라서 프로젝트의 사이즈가 플라스크보다 크다.


가상환경 설치하기

# 파이썬 가상환경 모듈 설치
$ pip install virtualenv

# 현재 디렉토리에 새 virtualenv 가상환경 만들기
$ virtualenv <가상환경 이름>

# 가상환경 진입하기
$ source venv/bin/activate

# 장고 설치
$ pip install django

# 장고 설치 확인
pip freeze

# 장고 시작. 프로젝트 파일이 생성된다.
django-admin startproject <project name>

생성된 프로젝트 파일 안으로 들어가면 다음과 같은 두 파일이 있다.

  • manage.py
  • <프로젝트 이름>파일
    여기서 manage.py를 이용해서 서버를 가동할 수 있다.
    # 파이썬 가동하는 방법
    $ python manage.py runserver
    

http://127.0.0.1:8000/ 라는 링크가 뜰 것이다.
접속하면 Congratulations on your first Django-powered page.라고 뜬다. 장고가 잘 설치된 것이다.


django의 구성 요소

  • manage.py : 장고를 실행하는 부분. python manage.py runserver을 통해 실행된다.
  • __init__.py는 이 디렉토리가 파이썬 모듈로써 인식되도록 하는 역할을 한다.
  • asgi.py, wsgi.py는 서버에서 장고 프로젝트를 다룰 때 쓰게 된다.
  • settings.py : 프로젝트를 하면서 가장 많이 보게 될 것이다. 전반적인 프로젝트의 설정사항을 반영하는 파일이다.
  • urls.py : 프로젝트를 하면서 가장 많이 보게 될 것이다. url을 관리하는 곳이다.

django Project and App

한 Project는 여러 App으로 구성되어 있다.
App 각각은 특정 명령을 수행하는 뷰나 템플릿의 모음이다.
한 사이트에 여러 기능들이 있는 페이지가 있듯이!
각 기능들에 대해서 모듈화를 해서 개별적으로 진행할 수 있다.
예를 들어, 한 프로젝트가 있으면 블로그 앱, 스포츠 앱, 카페 앱 등으로 이루어질 수 있다.


django App 만들기

# 프로젝트 안에서 startapp을 수행한다.(manage.py와 동일 경로에서 수행)
(venv) yeochaelin@yeochaecBookPro webproj % django-admin startapp homepage



django의 MVT Pattern

png
유저가 Django에게 HTTP request를 보낸다. Django,즉 서버는 URL에서 urls.py로 url을 인식한다.
만약 들어온 경로가 urls.py에 있다면 이를 View에 보낸다. views.py라는 파일에서 들어온 요청을 처리하게 된다.
데이터베이스를 처리하게 되는 경우 Model에서 데이터베이스를 처리하게 된다.
장고의 경우 데이터베이스를 ORM 구조로 관리한다.
요청에 응답하기 위해 특정 웹페이지를 보여줘야 한다면, Template 에서 .html파일을 통해 처리를 한다.
html에서 template 언어를 통해 뷰 단에서 처리한 변수를 처리할 수 있다.



View로 Request Handling 하기

views.py에 다음과 같이 함수를 짠다.

from __future__ import unicode_literals
from django.shortcuts import HttpResponse, render

# Create your views here.
def index(request):
    # 어떤 요청이 들어왔을 때, "Hello World!"라는 response를 주는 뷰이다.
    return HttpResponse("Hello World!")


urls.py에서 경로를 추가해 뷰가 실행될 url을 지정해준다.

from django.conf.urls import path
from django.contrib import admin
from hompage.views import index

urlpatterns = [
    path('', index), # 127.0.0.1/
    path('admin/', admin.site.urls),
]


settings.py의 INSTALLED_APPS에 ‘homepage’를 추가해줘야 한다. 그렇지 않으면 장고 프로젝트가 homepage를 설치된 앱으로 인식하지 않는다.

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'homepage',
]

manage.py가 있는 경로에서 다음을 실행하면

python3 manage.py runserver

http://127.0.0.1:8000/ 에서 Hello World!가 뜨는 것을 볼 수 있다.
동작방식

  1. 클라이언트가 127.0.0.1이라는 주소에 요청을 보낸다
  2. urls.py에서 주어진 패턴이 url에 있는지 확인한다. 있으면, index를 실행한다.
  3. views.py에서 index함수를 실행한다. 즉, HttpResponse인 “Hello World!”를 출력한다.
    장고는 기본적으로 어드민 페이지(관리자 페이지)를 제공한다.
    127.0.0.1/admin/으로 접속하면 뜬다.
    관리자 계정을 만들어야하는데, 이는 CLI 환경에서 진행할 수 있다.
    만약 이 부분에서 막힌다면 django의 버전이 낮기 때문인데, 다음과 같이 업그레이드를 진행해준다.
    python3 -m pip install --upgrade django
    python -m pip install --upgrade django
    

    CLI에서 슈퍼유저를 만들어 관리자 계정을 생성해보자.

    python3 manage.py createsuperuser
    python3 manage.py migrate
    

    다음과 같이 계정의 이름, 이메일, 비밀번호를 설정해주자.

    (venv) yeochaelin@yeochaecBookPro webproj % python3 manage.py createsuperuser
    Username (leave blank to use 'yeochaelin'): chaelin
    Email address: gomgomtoto@gmail.com
    Password: 
    Password (again): 
    Superuser created successfully.
    


    다시 python3 manage.py runserver로 admin페이지에 들어가 로그인을 해보면 잘 된다!
    사용자를 관리하는 기능이 이미 내장되어 있어 정말 편하다.
    데이터베이스 자체를 관리할 수도 있다!



Template으로 보여줄 화면 구성하기

views.py의 index함수에 다음과 같이 추가해준다.

def index(request):
    return render(request, 'index.html', {})

HttpResponse에는 html이라는 마크업 문서를 작성할 수 있다.
html문서를 따로 관리해줄 수 있는 함수인 render라는 함수를 추가해준다. render는 세가지 파라미터를 갖는데,
첫번째 파라미터 : index 함수에 들어온 http request
두번째 파라미터 : 응답을 하는 과정에서 보여줄 파일이름
세번째 파라미터 : request와 .html을 처리하는 과정에서 사용할 인자들(데이터)을 딕셔너리 형태로 전달

html을 관리하는 방법은 여러가지가 있는데, 각 앱의 디렉토리에서 관리하는 것을 해보자.
앱의 목적에 따라 디렉토리 구조는 계속 바뀔 수 있다.
이것은 하나의 예시일 뿐!
homepage라는 앱에 template이라는 새로운 폴더(디렉토리)를 만든다.
그리고 이 template의 하위에 index.html이라는 파일을 만든다.
index.html을 다음과 같이 작성해보자.

<!DOCTYPE html>
<html>
    <head>
        <title>Python django example</title>
    </head>

    <body>
        <h1>Title</h1>
        <p>blah blah blah...</p>
    </body>
</html>

html은 크게 두 부분으로 이루어져 있는데, <head><body>이다.
<head>는 html파일에 대한 메타적인 정보, 즉 우리가 직접적으로 보는 부분이 아니라 그 뒤에서 이루어지는 부분을 주로 작성해준다.
<body>는 사용자가 직접 눈으로 확인하는 요소를 작성해준다.
<!DOCTYPE html>는 가장 최근의 html5 문서임을 강조하기 위해 써준다.

이제 template파일이 어디에 있는지 명시해줘야 한다.
settings.pyTEMPLATES'DIRS'에 이를 명시해줄 수 있는데,
'DIRS': ['homepage/template/index.html'],이와 같이 적어준다면 문제가 발생할 수 있다.
웹프로젝트 전체 폴더가 이 컴퓨터상의 어디에 있는지 장고는 알 수 없다.
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))라는 이 변수는 우리 프로젝트의 파일들이 컴퓨터의 어디에 존재하는지 알려준다.
따라서 다음과 같이 적어줄 수 있다.

'DIRS': [BASE_DIR + 'homepage/template/index.html'],

하지만 디렉토리를 합치는 전문적인 함수를 사용해주는것도 좋은데, 우선 import os를 해준 뒤,

'DIRS': [
    os.path.join(BASE_DIR, "homepage", "template"),
    ],

이처럼 적어주면 좋다. os.path.join은 여러 인자를 받을 수 있다.

정리하자면 우리는 총 3가지 작업을 해줘야 했다.

  1. request에서 보여줄 화면을 template 파일 아래 index.html을 만들어 구성
  2. view에서 html파일을 렌더함수의 인자로써 전달
  3. settings에서 TEMPLATES의 디렉토리 값으로 template 전달

실행해보면 다음과 같이 페이지가 잘 뜨는 것을 볼 수 있다.
png
<title>부분에 적은 것이 사이트의 이름으로 뜨고, 내용으로는 <body>에 적어준 것들이 잘 출력된다.


이제 뷰에서 딕셔너리를 전달하는 부분을 바꿔보자.
렌더링이라함은, 단순히 어떤 내용을 보여주기보다는 어떤 데이터를 바탕으로 html안의 내용을 완성한다는 의미에 가깝다.
따라서 딕셔너리에 자료를 전달해줌으로써 안에 있는 데이터와 html을 합쳐 통합적인 템플릿을 완성할 수 있다.
views.py의 index함수를 다음과 같이 수정한다.

def index(request):
    number = 10
    return render(request, 'index.html', {"my_num" : number})

이제 my_num을 index.html에서 사용할 것인데, 이를 사용하기 위해 장고 템플릿 언어를 사용한다. 장고 템플릿 언어는 html에서 부가적으로 사용할 수 있는 언어인데,


를 이용해 쓴다. 이를 템플릿 변수라고 한다.
index.html을 다음과 같이 수정해준다.

<!DOCTYPE html>
<html>
    <head>
        <title>Python django example</title>
    </head>

    <body>
        <h1>Title</h1>
        <p>blah blah blah...</p>
        <p></p>
    </body>
</html>

png
실행해보면 다음과 같이 my_num인 10이 잘 출력되는 것을 볼 수 있다.
이런식으로 정해진 내용만이 아닌 동적인 웹사이트를 만들 수 있다!


이제, 템플릿 변수에 적용할 수 있는 템플릿 필터에 대해 알아보자.
템플릿 필터는 변수의 값을 특정 형식으로 변환하는 데 사용한다.
예를 들어, 어떤 값이 있을 때 그 값의 길이나 그 값에 대해 특정한 값만 원할 때 템플릿 필터를 사용할 수 있다.
views.py를 다음과 같이 바꿔보자.

def index(request):
    name = "Michael"
    return render(request, 'index.html', {"my_name" : name})

index.html의 템플릿 변수 이름도 맞춰서 바꿔준다.

<!DOCTYPE html>
<html>
    <head>
        <title>Python django example</title>
    </head>

    <body>
        <h1>Title</h1>
        <p>blah blah blah...</p>
        <p></p>
    </body>
</html>

python3 manage.py runserver를 실행시켜보면 다음과 같이 웹브라우저에서 문자열을 렌더링하는 것을 확인할 수 있다.
png
우리는 이 상황에서 이 템플릿 변수에 템플릿 필터를 적용할 수 있다.
템플릿 필터는 기본적으로 파이프라인 기호를 사용한다.
my_name|length 으로 템플릿 필터를 적용할 수 있다. 이 경우, my_name의 길이를 반환해준다.
index.html의 템플릿 변수를 이처럼 수정해주면 결과는 다음과 같다.
png
Michael의 문자열 길이가 7이므로 결과는 7로 나온다.

my_name|upper 이렇게 하면, my_name에 대해서 모두 대문자로 출력해주는 필터이다.
png

이처럼 템플릿 필터는 다양한 기능이 있고, 종류도 굉장히 많기 때문에 여기서 다 다루기보다는 도큐먼트 등을 참고해서 필요할 때 적용하도록 하자.

이제 템플릿 태그에 대해 알아보도록 하자. html 파일자체에는 어떤 프로그래밍적 로직을 도입할 수는 없다. 하지만 장고를 사용하는 과정에서는 장고 템플릿 언어라는 것을 사용할 수 있었고, 여기서는 “템플릿 태그”라는 것을 사용할 수 있다.
어떠한 태그는 태그를 닫아줘야 하는 형태도 존재한다.
즉 태그와 엔드태그 사이에 어떤 로직을 집어넣을 수 있다.
템플릿 태그도 종류가 굉장히 다양해서 도큐먼트를 통해 원하는 태그를 찾아 쓰면 된다. 여기서는 가장 많이 사용하는 for와 if를 알아보자.

for 태그는 파이썬에서 사용했던 for문을 html에서도 사용할 수 있게 해준다.
우선 views.py에서 index함수를 수정해 숫자 리스트를 만들자.

def index(request):
    nums = [1, 2, 3, 4, 5]
    return render(request, 'index.html', {"my_list" : nums})

index.html을 다음과 같이 수정해준다.

<!DOCTYPE html>
<html>
    <head>
        <title>Python django example</title>
    </head>

    <body>
        <h1>Title</h1>
        <p>blah blah blah...</p>
        
    </body>
</html>

결과는 다음과 같다.
png

이제 if태그에 대해 알아보자.
if 태그의 경우 어떤 조건에 따라 랜더링해줄 html부분이 달라질 때 사용한다.
my_list의 숫자 중에서 element가 홀수인 경우만 출력해보자.
if 태그의 경우, 템플릿 필터를 이용해 조건을 걸어줄 수 있다.
element 중 홀수만 출력하려면, element가 어떤것으로 나눠떨어지는지 체크해야한다. 이때 사용하는 필터가 divisibleby이다.
템플릿 필터에도 콜론(““)을 통해 파라미터를 전달할 수 있다. “2”라고 쓰면 element가 숫자 2로 나눠 떨어지게하는 조건을 쓸 수 있다.
홀수만 출력하기 위해서는 위의 조건을 부정하는 element만 출력하면 된다. 따라서 다음과 같이 된다.

<!DOCTYPE html>
<html>
    <head>
        <title>Python django example</title>
    </head>

    <body>
        <h1>Title</h1>
        <p>blah blah blah...</p>
        
    </body>
</html>

png
결과를 보면 다음과 같이 홀수가 잘 출력되는 것을 알 수 있다.