Dynamic Web Web Application Program
Python web framework
어느 기업에서 쓰는가?
구조
MVC(model view controller) 소프트웨어 디자인 패턴
MTV(model template view) 같은 의미지만 django에서는 다르게 씀
pip install django
django-admin startproject 플젝이름
django-admin startproject 플젝이름 .
python manage.py runserver
django extension
// settings.json
{
... 생략 ...,
// Django
"files.associations": {
"**/*.html": "html",
"**/templates/**/*.html": "django-html",
"**/templates/**/*": "django-txt",
"**/requirements{/**,*}.{txt,in}": "pip-requirements"
},
"emmet.includeLanguages": {
"django-html": "html"
}
}
pylance
__init__.py
asgi.py
setting.py
LANGUAGE_CODE = 'ko-kr'
: 한글로 번역이 되어서 나옴TIME_ZONE = 'Asia/Seoul'
: 데이터베이스 연동시간 서울표준시간으로urls.py
wsgi.py
BASE_DIR
프로젝트 루트 폴더, 설정 파일이나 py 파일 등에서 프로젝트 루트 폴더를 찾아 그 하위를 탐색하거나 하는 일을 수행합니다.
SECRET_KEY
보안을 위해 사용 됩니다.
세션값의 보호나 비밀번호 변경시 사용되는 보안 URL을 만드는 일 등에 사용
DEBUG
ALLOWED_HOSTS
INSTALLED_APPS
MIDDLEWARE
ROOT_URLCONF
기준이 되는 urls.py의 경로를 설정합니다.
TEMPLATES
WSGI_APPLICATION
DATABASES
AUTH_PASSWORD_VALIDATORS
LANGUAGE_CODE
장고 서버로 요청(request)이 들어오면, 그 요청이 어디로 가야하는지 인식하고 관련된 함수(view)로 넘겨준다.
views.py
에서 만든 함수를 연결시켜준다.
# first_project/urls.py
from django.contrib import admin
from django.urls import path
from articles import views
urlpatterns = [
path('admin/', admin.site.urls),
path('index/', views.index),
]
# articles/views.py
def index(request): # 첫번째 인자는 반드시 request
return render(request, 'index.html') # render의 첫번째 인자도 반드시 request
views.py
에서 지정한 index.html
파일을 만들자.
Django에서 template이라고 부르는 HTML 파일은 기본적으로 app 폴더안의 templates 폴더 안에 위치한다.
<!-- articles/templates/index.html -->
<h1>만나서 반갑습니다!</h1>
python manage.py startapp 어플리케이션이름
__init__.py
admin.py
apps.py
models.py
test.py
views.py
urls.py
프로젝트.settings.py
열기
INSTALLED_APPS = [ ... ]
이곳에 맨 상단에 application이름
을 적기
보통 application의 적는 순서는 이렇게 구성됨
보게되면 리스트 맨 뒤에 요소 뒤에 ,
가 붙은 것을 확인할 수 있음(trailing comma)
django에서 권장되는 문법임
프로젝트폴더.urls.py
urlpatterns = [
path('admin/', admin.site.urls),
# path 첫번째 인자 : 연결시킬 주소
# path 두번째 인자 : 어떤 View(application.함수명)를 연결시킬 것이냐
]
Application이름.views.py
def index(request) : # view함수의 첫번째 인자는 request이어야함
return render(request, '템플릿경로')
# 랜더링의 첫번째 인자도 request이어야함
# 두번째 인자는 template 경로
프로젝트폴더.urls.py
from articles import views # application의 view를 import 시키기
urlpatterns = [
path('admin/', admin.site.urls),
path('index/', views.index), # 방금 만든 views의 함수를 연동시킴
]
application폴더
내부에 templates
폴더 생성def index(request) : # view함수의 첫번째 인자는 request이어야함
return render(request, 'index.html') # 템플릿경로 작성
{{ 변수명 }}
.
)을 사용하여 변수 속성에 접근할 수 있음{{ 변수명|filter }}
{{ name|lower }}
: name 변수를 모두 소문자로 출력{{ 변수명|truncatewords:30 }}
<h3> 3. Length filter </h3>
<p> {{students|length}} </p>
{% for fruit in fruits %}
{% if fruit|length > 3 %}
<p>{{fruit}} 과일 이름이 기네요? </p>
{% else %}
<p>{{fruit}} 과일 이름이 짧네요 </p>
{% endif %}
{% endfor %}
<hr>
<h3> 5. 글자필터 </h3>
<p> {{ 'JIYOUNG'|lower}} </p>
<p> {{'ji young'|title}} </p>
<p> {{ students|random}} </p>
<br>
<hr>
<h3> 6. 연산 </h3>
<p> {{4|add:6}} </p>
<h3> 7. 날짜 </h3>
{% comment %} 현재시간을 여러 형태로 바꿔서 보여주기 {% endcomment %}
<p> {% now "DATETIME_FORMAT" %}</p><!-- 2021년 3월 9일 12:40 오후-->
<p> {% now "SHORT_DATETIME_FORMAT" %}</p><!--2021-3-9 12:40 -->
<p> {% now "DATE_FORMAT" %}</p><!--2021년 3월 9일 -->
<p> {% now "SHORT_DATE_FORMAT" %}</p><!-- 2021-3-9.-->
<p> {% now "Y년 m월 d일 h:i" %}</p> <!--2021년 03월 09일 12:40-->
<p> {% now "Y년 m월 d일 (D) A h:i" %} <!-- 2021년 03월 09일 (화요일) 오후 12:44-->
{% comment %} 출력결과를 변수로 저장해서 활용하기 {% endcomment %}
{% now "Y" as current_year %}
<p>{{ current_year}}</p><!-- 2021-->
{% tag %}
{% tag %}
... {% endtag %}
<h1>DTL 연습페이지</h1>
<hr>
<h3>1. for </h3>
<p> for 문 돌릴 것 : {{students}}</p>
{% for student in students%}
<p>{{student}}</p>
{% endfor %}
<br>
<p>for 문 인덱스사용하기 </p>
{% for fruit in fruits%}
<p>{{ forloop.counter }} {{fruit}} </p>
{% endfor %}
<br>
<p>for문 비어있을 경우</p>
{% for user in user_list %}
<p> {{ user }} </p>
{% empty %}
<p> 유저정보가 없습니다 </p>
{% endfor%}
<br>
<hr>
<h3> 2. if </h3>
{% if '김지용' in students %}
<p> 반장있어요 </p>
{% else %}
<p> 반장없음 </p>
{% endif %}
<br>
{% for student in students %}
{% comment %} 루프에서 첫번째 이면 {% endcomment %}
{% if forloop.first %}
<p> 첫번째 학생은 {{student}}님 입니다. </p>
{% else %}
<p> {{stduent}} </p>
{% endif %}
{% endfor %}
<br>
{% lorem [count] [method] [random] %}
count | 생성 할 단락 또는 단어 수를 포함하는 숫자 (또는 변수)입니다 (기본값은 1). |
---|---|
method | 어느 w 단어에 대한 p HTML 단락 또는 b 일반 텍스트 단락 블록 (기본값입니다 b ). |
random | random 주어진 경우 단어 는 텍스트를 생성 할 때 공통 단락 ( "Lorem ipsum dolor sit amet…")을 사용하지 않습니다. |
{# lorem ipsum #}
{# {% if .. % }text{% else %} #}
{% comment %}
와 {% endcomment %}
사이에 입력{% extends %}
{% block %}
{% endblock %}
태그에 이름 지정base.html 하고 (위치 : 프로젝트/templates 폴더 만들고 안에)
{% extends 'base.html' %}
{% block content %}
<h1> 만나서 반가워요 </h1>
{% endblock %}
플젝.settings 에서 templates
app_dirs:True
: 이거는 templates/ 경로를 생략해도 되는 이유
myapp/
templates/
blog/
list.html
post.html
dirs
: 여기에
`[BASE_DIR / 'firstpjt' / 'templates'],
python pathlib
이렇게 사용시 os에 따른 경로표현(window는 역슬래쉬, mac은 슬래쉬)에 상관없이 경로 표현이 가능해짐
settings 상단에 찾아보면 BASE_DIR = Path(__file__).resolve().parent.parent
이런게 있음
의미는 현재 프로젝트 최상단 디렉토리 위치임
템플릿 로더는 먼저 《DIRS》 디렉토리에서 템플릿을 찾습니다.
?key=value&key=value
형태로 전달첫번째 view = 데이터 받는 template
프로젝트.urls
> urlpatterns 에 path('throw/', views.throw),
추가
어플리케이션.views
에 throw 함수 추가
def throw(request) :
return render(request, 'throw.html')
어플리케이션.templates
에 throw.html 추가
{% extends 'base.html' %}
{% block content %}
<h1>THROW</h1>
{% comment %} action은 어느 페이지로 넘겨줄지 {% endcomment %}
<form action="/catch/" method="GET">
<label for="message">Throw: </label>
<input type="text" name="message" id="message">
<input type="submit">
</form>
{% endblock %}
두번째 view - 보내준 데이터 받는 view
프로젝트.urls
> urlpatterns 에 path('catch/', views.catch),
추가
어플리케이션.views
에 throw 함수 추가
def catch(request) :
message = request.GET.get('message') # request 객체에서 GET 에서, throw에서 text input의 name = message
context = {
'message' : message,
}
return render(request, 'catch.html', context)
어플리케이션.templates
에 catch.html 추가
{% extends 'base.html' %}
{% block content %}
<h1>{{message}}</h1>
{% endblock %}
Django URLs
app의 view 함수가 많아지면서 사용하는 path() 또한 많아지고, app 또한 더 작성되기 때문에 프로젝트의 urls.py에서 모두 관리하는 것은 코드 유지보수에 좋지 않음
이제는 각 app에 urls.py를 작성하게 됨
원래 app에 urls.py는 없다.
근데 여러개의 app으로 구성될경우 프로젝트.settings
에서 import 받을 때 충돌이 나겠지? 물론 as를 이용해서 각각 이름을 나눠줘도 되긴 하지만 복잡해짐
어플리케이션.urls.py
from django.urls import path
from . import views # django는 명시적인 경로 표현을 선호함
urlpatterns = [
# 원래 프로젝트.urls에 있던 것을 가져옴 - admin 제외
path('index/', views.index),
path('greeting/', views.greeting),
path('throw/', views.throw),
path('catch/', views.catch),
]
두번쨰어플리케이션.urls.py
from django.urls import path
from . import views # django는 명시적인 경로 표현을 선호함
urlpatterns = [
# 두번째 어플리케이션 내부의 view를 연동
]
그럼 project의 urls는 아무런 역할을 안하냐?
그것은 아님 articles.urls
로 갈지 pages.urls
로 갈지 판단하여 넘겨줌
from django.contrib import admin
from django.urls import path, include # app의 urls 로 넘기기 위해 include 추가
from articles import views
urlpatterns = [
path('admin/', admin.site.urls),
# path 첫번째 인자 : 연결시킬 주소
# path 두번째 인자 : 어떤 View(application.함수명)를 연결시킬 것이냐
path('articles/', include('articles.urls')),
path('pages/', include('pages.urls')),
]
주소 자체를 변수처럼 사용해서 동적으로 주소를 만드는 것
하는 법
urls
path('hello/<str:name>/', views.hello), # str: 은 기본값이라 생략가능, int나 다른 변수형은 명시해주어야함
views.py
def hello(request, name) : # 주소로 넘겨받은 name변수값
context = {
'name' : name,
}
return render(request, 'hello.html', context)
# firstpjt/urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('articles/', include('articles.urls')),
path('pages/', include('pages.urls')),
]
include()
path('index/', views.index, name='index')
<a href="{% url 'index' %}">메인 페이지</a>
{% url '' %}
application이 많아질 경우 naming url 사용시 어떤 application과 연동된 페이지인지 알기가 힘들어짐
어플리케이션.templates
안에 어플리케이션이름
폴더를 하나 더 만들고 그 안에 html 파일을 넣는 방식을 취함
app_name/templates/
경로에 있는 templates 파일들만 찾을 수 있으며, INSTALLED_APPS에 작성한 app 순서로 tamplate을 검색 후 렌더링app_name/templates/app_name
형태로 변경해 임의로 이름 공간 생성 후 변경된 추가 경로 작성하는 것임어플리케이션.urls
에서 app_name 속성 활성화app_name
attribute 값 작성app_name = '어플리케이션이름'
urlpatterns = [
...
]
view 단에서 연결시켜줄 때 어플리케이션/페이지이름.html
로 접근
def lotto(request) :
now_lotto = random.sample(range(1:46), 7)
context = {
'now_lotto6' : now_lotto[:6],
}
return render(request, 'pages/lotto.html', context)
실제페이지에서 연동할 때 어플리케이션.urls.py > app_name
의 속성에 의하여 연동됨
{% url 'pages:lotto' %}
와 같이 url 이후 해당어플리케이션:페이지
로 어느 어플리케이션에서 쓰는지 명시하면서 사용