Django 프레임워크 (2)

cjkangme·2023년 5월 11일
0

에이블스쿨

목록 보기
70/81
post-thumbnail
post-custom-banner

Static File

Static File이란?

웹 페이지를 구성할 때 쓰임이 정해져 있는 ‘움직이지 않는’ 파일을 의미한다.

js, css, 이미지 파일 등이 여기에 해당한다.

Django에서 Static 파일 관리하기

settings.py

settings.py에서 static file을 디렉토리 별로 관리할 수 있다.

STATIC_URL = "static/"
STATICFILES_DIRS = [
    BASE_DIR / 'static',
]
  • STATICFILES_DIRS : static 파일의 경로를 지정하는 변수이다. 프레임워크 문법이기 때문에 반드시 이름을 그대로 사용해야 한다.
  • BASE_DIR : 프로젝트의 루트 폴더 경로를 말한다. django 프로젝트 폴더 생성 시 자동으로 지정된다.
  • STATIC_URL : 웹 페이지 경로를 지정한다.

위와 같이 설정했다면 프로젝트 루트폴더에 static 이름을 갖는 디렉토리를 생성하여 파일을 집어넣고, 브라우저에서 /static/filename.jpg 경로로 접근하면 해당 파일을 볼 수 있다.

함수에서 직접 파일 관리하기(동적)

# views.py
from django.http import FileResponse

def load_img(req, name):
	img = open(f'static/ {name}', 'rb')
	return FileResponse(img, content_type= 'image/jpeg' )

# urls.py
urlpatterns = [
    path("image/<name>", views.load_img)
]

파이썬의 파일문법을 이용해서 직접 이미지를 불러오는 방법도 있다.

FileResponse 함수를 이용해 다양한 타입의 static file을 화면에 출력할 수 있다.

주로 특정 파일을 사용자에게 다운로드 받도록 하거나, 사용자가 첨부한 파일을 받아 처리하는 경우 이러한 방식으로 처리하는 것이 가능하다.

파일을 처리하는 3가지 방법

  1. WSGI 앞단의 웹 서버(nginx, Apache)에게 처리를 맡김
    • 가장 효율적인 방법이나 세팅이 어려움
    • 대규모 트래픽이 발생하는 서버에서 사용
  2. web server를 따로 분리해서 운영
    • 세팅이 간단하고 효율적
    • 도메인을 분리하여 사용해야한다는 단점
  3. static 연결하여 처리 (settings.py)
    • 가장 세팅이 쉽다
    • 별도의 url을 통해 접근하여 받아오는 식으로 낮은 효율 (소규모 시스템에 적합)

Django Template

HTML과 같이 사용자에게 보여주는 틀을 말한다.

Template을 별도 관리하는 이유는 로직(python 코드)과 Look(HTML)을 분리하기 위해서이다.

django의 template 문법을 통해 HTML에 동적으로 변수를 할당하고, 파이썬과 유사하게 조건문 및 반복문의 사용 등이 가능하다.

Template 관리

settings.py의 TEMPLATE 변수아래 템플릿 디렉토리를 선언하여 해당 디렉토리에 템플릿 파일들을 담는다.

TEMPLATES = [
    {
        "BACKEND": "django.template.backends.django.DjangoTemplates",
        "DIRS": [BASE_DIR / 'templates'],
        "APP_DIRS": True,
				... (중략) ...
		}
]

django가 제공하는 render 함수를 통해 해당 템플릿 파일을 가져올 수 있다.

# urls.py
urlpatterns = [
    path("hello/", views.index),
]

# views.py
from django.shortcuts import render

def index(req):
    return render(req, 'hello.html')

이렇게 하면 ROOT/templates/hello.html 경로에 있는 html 파일을 불러온다.

render 함수는 HTML 외의 다양한 형식의 파일을 렌더링할 수 있는데 자세한 것은 따로 공부해두면 좋다.

Template 주요 문법

참고 : https://docs.djangoproject.com/en/4.2/ref/templates/builtins/

프레임워크에 문법에 따라 Template을 동적으로 렌더링할 수 있다.

변수

HTML에 변수를 선언하면 렌더링시 해당 부분을 파이썬 코드의 데이터로 교체할 수 있다.

Template에서 교체할 컨텐츠를 중괄호 2개 {{ }} 로 표시한다.
함수에서는 Template에서 교체할 컨텐츠를 딕셔너리에 담아 render 함수의 인자로 사용한다.
이때 템플릿에 선언한 변수명과 함수에서 전달하는 딕셔너리의 key가 동일해야 한다.

<!-- HTML -->
<h2>{{title}}</h2>
<p>{{content}}</p>
# views.py
def chapter(req, id):
    chapters = {
        "01": {"title": "Setting & Deploy" , "content": "Setting & Deploy is ..." },
        "02": {"title": "Routing & View" , "content": "Routing & View is ..." },
    }
    return render(req, 'index.html', chapters[id])

# urls.py
urlpatterns = [
    path("chapter/<id>/", views.chapter),
]

필터

변수에는 filter를 선언하여 해당 변수에 대한 동적인 처리를 할 수 있다.

외우기보다는 필요한 것을 그때그때 공식문서에 찾아 사용하면서 자연스럽게 익히자

  • length : 리스트, 문자열, 딕셔너리의 길이
  • truncatechrs : 문자열을 지정한 길이까지만 출력
    • 문자열이 지정한 길이보다 길면 “…” 으로 표시하여 생략
  • date : 날짜 객체를 지정한 포맷으로 출력
  • escape : 문자열에서 HTML 태그를 이스케이프 처리
    • HTML 형식으로 데이터를 보내도, 그대로 문자열로 처리
  • safe : 문자열에서 HTML 태그를 이스케이프 처리하지 않고 출력
    • 교체한 문자열을 문자열이 아닌 기존 HTML의 태그처럼 처리

필터 사용 예시 예시

  • {{key | filter}} 형식으로 사용할 수 있다.
def index(req):
    d = {
        'title': 'django',
        'content': '<a href="https://www.djangoproject.com/">Django</a> is...'
    }
    return render(req, 'index.html', d)
<!-- HTML -->
<p>{{content}}</p>


위와 같이 렌더링 시 HTML 태그를 직접 담아 전송할 경우 이를 태그로 처리하지 않고 그대로 문자열이 된다.

safe 필터를 이용하면 문자열을 태그로 처리하여 사용할 수 있도록 해준다.

<!-- HTML -->
<p>{{content | safe}}</p>

조건문 & 반복문

Template 내에서 조건문 및 반복문을 사용할 수 있는 문법이다.

  • 조건문
<!-- HTML -->
{% if variable %}
<p>조건이 참입니다.</p>
{% elif another_variable %}
<p>다른 조건이 참입니다.</p>
{% else %}
<p>모든 조건이 거짓입니다.</p>
{% endif %}
  • 반복문
<!-- HTML -->
{% for item in items %}
<p>{{ item }}</p>
{% empty %}
<p>아이템이 없습니다.</p>
{% endfor %}

위와같이 선언하면 되며, 파이썬의 문법을 그대로 사용할 수 있다.

예를들어 딕셔너리 형태의 파일의 key, value를 모두 사용하고 싶다면 .items 와 같은 형태로 사용할 수 있다. (파이썬 문법과 달리 소괄호를 빼야함에 유의하자)

사용 예시

<ul>
{% for key, item in item_dict.items %}
    <li>{{key}} : {{ item }}</li>
{% empty %}
    <li>아이템이 없습니다.</li>
{% endfor %}
</ul>
def control(req):
    data = {
        'item_list' : ['사과', '딸기', '메론'],
        'item_dict' : {
            '강아지' : 4,
            '고양이' : 4,
            '비둘기' : 2
        }
    }
    return render(req, 'control.html', data)

extends & block

템플릿 상속을 위해 사용한다

웹페이지에서 공통적으로 사용이 되는 레이아웃, 헤더, footer 등에 사용한다.

상속받은 extends 템플릿에서 block을 사용하여 특정 부분만 변경할 수 있다.

Django Application

프로젝트의 기능별로 별도의 어플리케이션을 정의하여 구현하는 것

이를 통해 얻게되는 장점은 크게 두 가지가 있다.

  1. 유지보수를 쉽게 할 수 있다.
    1. 어떤 기능을 변경하고자 할 때 다른 기능에 영향을 주지 않고 해당 기능에 대해서만 변경이 가능
    2. 새로운 기능을 추가할 때 기존 기능과의 충돌을 걱정하지 않아도 된다.
  2. 재사용이 용이해진다.
    1. 다른 프로젝트에서 동일한 기능을 필요로 할 때 어플리케이션을 통채로 재사용 할 수 있다.

애플리케이션 생성하기

python manage.py startapp <애플리케이션 이름>

  • 해당 이름의 애플리케이션을 생성한다.

  • 프로젝트 디렉토리와 다른 구조의 애플리케이션 디렉토리가 생긴 것을 확인할 수 있다.

애플리케이션 디렉토리의 구조

  • admin.py : 관리자
  • migrations.py : 데이터 조정 및 이력관리
  • apps.py : 앱별 설정
  • model.py : 데이터의 구조 및 행동 정의
  • views.py : 페이지 구성 (컨트롤러)
  • tests.py : 유닛테스트

애플리케이션 등록하기

settings.py에 INSTALLED_APPS에 애플리케이션 이름을 추가해야한다.

INSTALLED_APPS = [
    "django.contrib.admin",
    "django.contrib.auth",
    "django.contrib.contenttypes",
    "django.contrib.sessions",
    "django.contrib.messages",
    "django.contrib.staticfiles",
    "<application_name>",
]

기본적으로 관리자 기능이 등록되어있다.

애플리케이션의 urls.py

기본적으로 모든 url은 프로젝트 디렉토리의 urls.py에서 관리된다.

하지만 프로젝트 디렉토리와 어플리케이션 디렉토리의 경로가 다르기 때문에 그대로 넣어 사용하면 오류가 발생할 가능성이 높다.

때문에 어플리케이션 별로 urls.py를 별도로 생성하고 django가 제공하는 include 함수를 이용해 묶어준다.

# project/urls.py
from django.urls import path, include

urlpatterns = [
    path("blog/", include('blog.urls')),
]

# application/urls.py
from django.urls import path

from . import views

urlpatterns = [
    path("list/", views.post_list)
]

# application/views.py
from django.http import HttpRequest, HttpResponse
from django.shortcuts import render

def post_list(req: HttpRequest) -> HttpResponse:
    posts = [
        { 'id': 1, 'title': 'html', 'content' : 'html is ...' },
        { 'id': 2, 'title': 'css', 'content' : 'css is ...' },
        { 'id': 3, 'title': 'javascript' , 'content' : 'javascript is ...' },
    ]
    return HttpResponse(posts)
  1. blog/ 로 시작하는 모든 경로는 어플리케이션의 urls.py에서 처리한다.
  2. 예를 들어 blog/list/ 주소가 오면 어플리케이션의 post_list 함수가 실행된다.

애플리케이션의 Template 처리

애플리케이션의 템플릿 역시 프로젝트 폴더의 templates 폴더에서 처리된다.

모든 어플리케이션의 Template를 하나의 디렉토리에서 처리해도 되지만, 구분을 위해서는 별도의 하위 폴더를 만들어서 관리하는 것이 권장된다.

번외 : Type Hinting
파이썬 및 Javascript는 인자 등을 주고 받을 때 타입체크를 하지 않는다.
→ int로만 작동하는 함수이지만 리스트, 문자열, 딕셔너리 등등 죄다 받을 수 있다.
소규모 프로젝트에서는 상관없지만 인터페이스가 복잡해지는 대규모 프로젝트에서 이로인한 에러 등 문제가 발생할 수 있다.

이때문에 파이썬은 3.9버전부터 Type Hinting 기능을 제공하고, Javascript는 TypeScript 언어가 생겨났다.

Django Admin

장고는 기본적으로 어드민페이지를 제공한다.

우리가 할 것은 어드민 계정을 추가하는 것 뿐이다.

그전에 어드민 계정을 추가한다는 것은 계정 데이터를 추가한다는 것이므로, 이를 저장할 DB가 필요하다.

DB 초기화

python [manage.py](http://manage.py/) makemigrations
python manage.py migrate
  • makemigrations : DB 구조에 맞도록 migrate 코드를 생성한다.
    • DB 구조가 변경될 때마다 적용해야함
  • migrate : DB를 초기화하는 코드

DB 확인

VS Code에 익스텐션을 설치하면 데이터베이스를 확인할 수 있다.

이번 과정에서는 SQLite Viewer 를 사용하였다.

  • migrate를 실행하지 않았을 때

  • migrate 수행 후

SQLite

  • Django가 기본으로 사용하는 DB
  • 파일기반 DB로 로컬에서 작동하며, 하나의 파일에 모든 데이터를 저장
  • 작은 규모의 데이터 처리에 적합
    • 프로젝트 규모가 커질 경우 다른 DB로 이동해야함

어드민 계정 생성

python manage.py createsuperuser
post-custom-banner

0개의 댓글