🚀 django URL 구성
일반적으로, python manage.py startapp [원하는 이름]로 앱을 생성한 후 views.py에 가서 view 관련 코드를 작성한 후,
config/urls.py에 등록해주는 방식으로 url와 view를 결합시킨다.
그런데 이런 방식은 url의 층위가 깊어질수록 관리하기 힘들어진다.
따라서 app 차원에서 별도로 urls.py를 생성해서 app 별로 url을 관리한 후 config/urls.py에 등록하는 방식으로 divided and conquer를 한다. 단, globalRouter는 core/urls.py에서 관리하도록 처리하자.
🚀뭔 소리야?
view 모델 정의 -> app 단위 urls.py에 등록 -> config/urls.py에 등록
우선 사용하고 싶은 views를 정의합니다. 브라우저에서 url로 이동하면 django에게 req를 날립니다.
이 req는 view에서 정의한 함수의 첫번째 인자로 들어갑니다.
이 req에는 is_auth, is_axax등 유용한 메서드가 많습니다. 나중에 사용해봅시다.
(https://docs.djangoproject.com/en/3.0/ref/request-response/)
한편, req를 받아 로직을 처리하는 view 함수에서는 이 적절한 res(HttpResponse object)를 돌려줘야 합니다.
# rooms/views.py
from django.http import HttpResponse
# Create your views here.
def all_rooms(req):
return HttpResponse(content="<h1>Hello</h1>")
정의한 view 함수를 적절한 app/urls.py에 넣어줍니다.
여기서 app_name은 config/urls.py에 지정한 namespace와 같은 이름이어야 합니다.
그래야 config/urls.py와 app 단위에 정의한 urls.py가 연결되겠죠~
"" 는 아무것도 없는 /을 의미합니다.
# core/urls.py
from django.urls import path
from rooms import views as room_views
app_name = "core"
urlpatterns = [
path("", room_views.all_rooms, name="home"),
]
config/urls.py에 생성한 urls.py를 urlpatterns에 포함시켜줍니다. namespace가 위에ㅐ서 작성한 app_name과 동일한 core인 것을 보실 수 있습니다.
# config/urls.py
from django.contrib import admin
from django.urls import path, include
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
path("", include("core.urls", namespace="core"),),
path("admin/", admin.site.urls),
]
위의 경우 / 와 /admin을 받게 됩니다.
url에 다른 새로운 것을 넣기 위해서는 위와 똑같은 과정을 거치면 됩니다.
view 모델 정의 -> app 단위 urls.py에 등록 -> config/urls.py에 등록
def room_detail(request):
return render(request, "rooms/detail.html")
from django.urls import path
from . import views as room_views
app_name = "rooms"
urlpatterns = [
path("1", room_views.room_detail, name="detail"),
]
urlpatterns = [
path("", include("core.urls", namespace="core"),),
path("rooms/", include("rooms.urls", namespace="rooms")),
path("admin/", admin.site.urls),
]
이 결과 /, /rooms/1, /admin을 받게 됩니다.
결국 아래와 같을 꼴로 정리하게 되는 셈입니다.
🚀 django template
Express에서 했던 것처럼, django도 HttpResponse를 직접 받아서 화면을 렌더링하기 보다 뷰 엔진 템플릿을 받아서 render하는 경우가 많습니다. 더 동적이고 편리하기 때문입니다.
django는 자체적인 Template Engine을 사용합니다. 사용합니다. flask에서 사용하는 Jinja2와 사용법이 비슷합니다.
config/settings.py에 가서 DIR 키의 값으로 templates의 경로를 알려줍시다. 저는 최상위에 templates라는 이름의 폴더를 만들고 그곳에서 html을 생성할 것이므로 다음과 같이 등록해주었습니다.
# config/settings.py
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",
],
},
},
]
render(req, 템플릿, 템플릿에 전달할 변수(context))
from datetime import datetime
from django.shortcuts import render
# Create your views here.
def all_rooms(req):
now = datetime.now()
return render(req, "all_rooms.html", context={"now": now, "hungry": True})
사용법은 다음과 같습니다.
<h1>Hello</h1>
<h3>the time is {{now}}</h3>
<div>
{% if hungry == True %}
I'm hungry
{% else %}
I'm not hungry\
{% endif %}
</div>
주의할 점은 템플릿 내에 함수를 실행할 때 독특하게 () 을 붙이지 않아도 실행된다는 것입니다.
보통 room.amenities.all()로 결과물을 불러오지만 템플릿 내에서는 ()를 붙이지 않아도 실행됩니다.
오히려 () 붙이면 작동하지 않습니다.
{% for a in room.amenities.all %}
<li>{{a}}</li>
{% endfor %}
템플릿 내에서 사용할 수 있는 연산이나 로직은 아래에 정리되어 있습니다.
템플릿 내에서는 +-*/ 가 불가능합니다~ 대신 add 필터 등을 사용합니다.
https://docs.djangoproject.com/en/3.0/ref/templates/builtins/
🚀 extends와 block, include
extends는 말 그대로 가능 기저 html를 연장하는데 사용합니다.
block은 특정 내용을 넣기 위한 창입니다. {% block [이름] %}{% endblock %} 으로 활용하시면 됩니다.
사용 방법을 보시면 pug와 같은 뷰 엔진과 사용법이 비슷한 것을 느끼실 수 있습니다.
# templates/base.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>{% block page_name%} {% endblock page_name%} | Airbnb</title>
</head>
<body>
{% block content %} {% endblock %} © airbnb
</body>
</html>
<!-- base -->
extends를 활용해서 base.html을 연장해서 사용합니다.
{% extends "base.html" %}
<!-- pagename block -->
block을 활용
{% block page_name%} Home {% endblock page_name%}
<!-- block-->
{% block content %}
{% for room in rooms%}
<h2>{{room.name}} / ${{room.price}}</h2>
{%endfor%}
{% endblock %}
한편, include는 단순히 무언가를 가져올 뿐입니다. 동적으로 바뀌지 않는 내용을 include로 가져오는 것이 좋습니다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>{% block page_name%} {% endblock page_name%} | Airbnb</title>
</head>
<body>
{% include "partials/header.html"%}
{% block content %} {% endblock %}
{% include "partials/footer.html"%}
</body>
</html>
'Django, Flask > 🔫 Django' 카테고리의 다른 글
Class Based Views(CBV) 근데 generic-display를 곁들인 (0) | 2020.06.16 |
---|---|
django로 pagination 구현하기 (+ querysets are lazy!) (0) | 2020.06.15 |
django-seed와 faker를 이용해 커스텀 명령어로 데이터 생성하기 (0) | 2020.05.13 |
custom django-admin commands (0) | 2020.05.13 |
모델 메서드 오버라이딩 : save()와 delete() 덮어쓰기 (0) | 2020.05.13 |