( ※ 일본의 한 블로거의 포스팅을 번역한 포스팅입니다. 오역이나 의역이 있을 수 있으며, 틀린 부분에 대해서는 지적해주시면 감사하겠습니다. )
Django를 사용하여 Web앱을 개발하고 있다. 처음부터 동시에 두 개의 어플리케이션 ( 같은 곳에 사용되나, 기능이 거의 다르므로 두 가지로 나누고 있다) 를 구축하고 있다. 그러나 하나를 만든 후 다른 하나를 만들 때 여러가지 걸리는 부분이 있었기 때문에 어떠한 부분에서 곤란을 겪었는지에 대해 써 볼 생각이다.
Django는 실제 환경에서 어떻게 동작하는지에 대해 작성하고 있는 포스팅이 생각보다 없는 인상이므로 이 포스팅이 도움이 되었으면 한다.
버전
명칭 | 버전 |
Python | 3.7.0 |
Django | 2.1.1 |
샘플
프로젝트로써 django_complex_sample이라는 것을 만들고 그 안에 app1, app2라는 어플리케이션을 만들었다.
■ 사전 준비
settings.py의 INSTALLED_APP에 app1과 app2를 추가한다. DB는 특별히 사용하지 않지만, SQLite로 해두자. 또한, URL도 지정해둔다.
(1) settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'app1',
'app2',
]
(2) urls.py
from django.contrib import admin
from django.urls import path
from app1 import views as v1
from app2 import views as v2
urlpatterns = [
path('admin/', admin.site.urls),
path('app1/', v1.HomeView.as_view(), name="app1home"),
path('app2/', v2.HomeView.as_view(), name="app2home"),
]
템플릿
■ 결론
표준대로 작성한다면,
① /templates/app_name 의 폴더를 만들고 거기에 파일을 저장한다.
② 뷰(View)로 부터 템플릿을 참고하는 경우, app_name/file_name으로 기재한다.
■ 근거
템플릿 | Django documentation | Django
템플릿은, view로 패스지정되어 페이지를 그릴때 사용된다. 표준대로 작성할 경우, 각 사이트에 templates라는 폴더를 만들더 그곳에 HTML을 배치해두면 사이트 표시될 때에 그 템플릿이 표시된다.
단지, 보여질 템플릿이 결정되는 것은 템플릿 폴더를 검색하여 처음에 발견한 파일을 사용하는 동작으로 작동하고 있다. 즉, 자동적으로 어플 마다 판정하고 있는 것은 아니다.
■ 예
예를 들어, app2의 templates바로 아래에 home.html을 두었다. app1에서의 같은 폴더는 아무것도 두지 않고 비워두었다. 그리고 app1의 뷰(view)에서 템플릿 명 home.html을 지정한다.
app1/views.py
from django.shortcuts import render
from django.views.generic import TemplateView
# Create your views here.
class HomeView(TemplateView):
template_name = 'home.html' # app1의home.html을 기대하고 있으나, 아직 만들어지지 않음.
def get(self, request, *args, **kwargs):
return render(request, self.template_name)
app1/home.html
<h1>Hello App1!</h1>
app2/home.html
<h1>Hello App1!</h1>
결과는 위와 같이, app2의 home.html을 참고하여 표시해버리고 만다. 이것은 templates의 검색으로 app2에 있는 home.html을 찾았기 때문이다.
이러한 결과를 피하기 위해 모든 어플리케이션 아래에 아래와 같이 폴더를 나눠,
app1/views.py
from django.shortcuts import render
from django.views.generic import TemplateView
# Create your views here.
class HomeView(TemplateView):
template_name = 'app1/home.html' # templates/app1폴더를 참고하도록
def get(self, request, *args, **kwargs):
return render(request, self.template_name)
참고하도록 하고자하는 폴더를 고정으로 지정하도록 하자.
정적 파일 (static)
■ 결론
- 각 어플리케이선 바로 아래에 /static/app_name 이라는 파일을 만들고, 그곳에 파일을 저장하자.
- 템플릿에서 파일을 참고하는 경우, app_name/file_name 이라고 기재하자.
■ 근거
정적 파일 (이미지, JavaScrop, CSS 등)의 관리 | Django documentation | Django
정적 파일이란, JavaScript나 이미지등 페이지에 삽입 형태로 사용하을 파일을 일컫는다. 개발시에는 각 어플리케이션 바로 아래에 static이라는 폴더를 만들어 그곳에 파일을 저장한다.
이러한 파일은 실제 환경에는 한 곳에 모두 모아 관리한다. collectstatic 커맨드로 정적 파일을 모을 수 있다. 시험삼아, static 폴더에 main.css파일 한 개만 배치하고, collectstatic을 실행해보자.
그럼, static 바로아래에 위치해버리고 만다. 이렇게 되면 복수의 사이트에 같은 파일명의 파일이 있을 때 서로 덮어쓰게 된다.
그러므로 각 어플리케이션의 static 바로 아래에 어플리케이션의 폴더를 작성하고 파일이 충돌하지 않도록 하자. 템플릿에서 참고하는 경우에도.
app1/home.html
{% load static %}
<script type="text/javascript" src="{% static 'app1/main.css' %}"></script>
와 같이 패스에 어플리케아션을 붙일 필요가 있으므로 개발 착수 시작부터 대응해두는 것이 좋을 것이다. static내에 어플리케이션 명의 폴더를 만들어 collectstatic을 실행하면 아래와 같이 된다.
URL (urls.py)
■ 결론
- 어플리케이션마다 urls.py를 작성한다.
- 각 어플리케이션의 urls.py에 고유의 app_name을 정의한다.
- 프로젝트의 urls.py에 각 어플리케이션의 정의를 include한다.
- 템플릿에서 어플명을 지정한다.
■ 근거
URL 디스패쳐 | Django documentation | Django
현재 프로젝트에 있는 urls.py는 아래와 같이 되어 있다.
django_complext_sample/urls.py
from django.contrib import admin
from django.urls import path
from app1 import views as v1
from app2 import views as v2
urlpatterns = [
path('admin/', admin.site.urls),
path('app1/', v1.HomeView.as_view(), name="app1home"),
path('app2/', v2.HomeView.as_view(), name="app2home"),
]
어플리케이션에서 URL이 증가한 경우에 여기에 정의를 늘려서 대응하는 것이 가능하다. 그러나 그렇게 한다면,
- URL을 재편성할 때마다 프로젝트의 수정해야한다.
- name의 명령 규칙이 알기 어렵게 되어버린다.
- 프로젝트쪽에 어플리케이션의 URL을 모두 관리하는 것은 힘들다.
위와 같은 문제들이 발생한다. 그러므로 Django에서는 include라는 기능이 준비되어 있다.
■ 예
먼저 각 어플리케이션의 바로 아래(어디든 괜찮지만)에 urls.py를 작성한다.
그리고 각 어플리케이션에 대해 URL을 기재한다.
app1/urls.py
"""app1의URL정의"""
from django.urls import path
from .apps import App1Config as config
from . import views as v
app_name = config.name # app1이 들어있다.
urlpatterns = [
path('', v.HomeView.as_view(), name='home'),
]
그리고 프로젝트의 urls.py에 그것을 include한다.
django_complex_smaple/urls.py
from django.contrib import admin
from django.urls import path, include
from app1 import urls as v1
from app2 import views as v2
urlpatterns = [
path('admin/', admin.site.urls),
path('app1/', include(v1)), # 변경(app1의URL을 추가)
path('app2/', v2.HomeView.as_view(), name="app2home"),
]
이렇게 작성해두면 자동적으로 app1의 URL에의 라우팅을 추가해준다. 또한 이 기능을 사용한 경우, view에서의 URL 지정 변경도 바뀐다. 먼저 app1에 적당한 뷰를 추가하자.
app1/views.py
from django.shortcuts import render
from django.views import View
from django.views.generic import TemplateView
from django.http import HttpResponse
# Create your views here.
class HomeView(TemplateView):
template_name = 'app1/home.html'
def get(self, request, *args, **kwargs):
return render(request, self.template_name)
class ApplicationView(View):
def get(self, request, *args, **kwargs):
return HttpResponse('GET request!')
app1/urls.py
"""app1의URL정의"""
from django.urls import path
from .apps import App1Config as config
from . import views as v
app_name = config.name # app1가 들어있다.
urlpatterns = [
path('', v.HomeView.as_view(), name='home'),
path('app/', v.ApplicationView.as_view(), name='app'), # 추가
]
작성된 view에 대해 home.html로부터 링크를 작성하자.
app1/templates/home.html
{% load static %}
<!DOCTYPE html>
<html lang="ja">
<head>
<link href="{% static 'app1/main.css' %}" rel="stylesheet">
</head>
<body>
<h1>Hello App1!</h1>
<a href={% url 'app1:app' %}>링크</a>
</body>
여기 코드에서 중요한 부분은 여기이다.
<a href={% url 'app1:app' %}>링크</a>
url이라는 Django 태그로 지정한 이름의 URL을 설정해주지만, {% url '[app_name]:[name]'%}과 href로 지정하면 어플명을 판정하여 그 링크를 만들어 준다. 이것에 의해 어플간의 이름 충돌을 방지할 수 있다.
참고자료
hiroronn.hatenablog.jp/entry/20181216/1544950291
'IT > WEB' 카테고리의 다른 글
[JavaScript] JavaScript의 Fetch API를 이용한 리퀘스트 송신하기 (0) | 2020.09.16 |
---|---|
[Django] 검색 게시판 만들기 ④ : 검색 기능 만들기 (0) | 2020.09.15 |
[Django] Django 개발에 대한 기본 상식 (2) | 2020.09.14 |
[Django] 검색 게시판 만들기 ③ : 게시판 목록 페이지 만들기 (0) | 2020.09.13 |
[Django] 검색 게시판 만들기 ② : 관리자 사이트의 커스터마이즈 (0) | 2020.09.11 |