<참고> 저번시간과 이어진다.
Template
사용자에게 보이는 부분으로 웹 페이지의 골격 = HTML로 작성된 부분
Django의 템플릿은 일반적인 HTML 작성과 거의 동일템플릿 태그(Template Tag {% %})
HTML이 파이썬 코드로부터 데이터를 바로 넘겨받아 손쉽게 처리할 수 있는 도구
HTML은 마크업언어 -> 정적인 웹페이지 -> 자바스크립트
{}로 감싸는 형태로 for문, if문 같은 파이썬 기본 구문에 사용 가능
ex) {% endif %}
View
템플릿과 모델 사이를 이어주는 다리 역할
모델을 통해 데이터에 접근
-> 템플릿으로부터 요청받은 데이터 처리 후 템플릿으로 보냄
1. 프론트엔드가 백엔드에게 데이터 요청
2. 백엔드에서 데이터를 뽑아옴
3. 데이터 처리 후 프론트엔드에게 제공
URL
라우팅 역할과 동시에 서버로 해당 주소에 할당된 리소스를 요청하는 역할
리소스 => HTML페이지, 내부를 채우는 데이터도 포함
결과 미리 보기
photo/templates/photo 폴더 생성
photo_list.html 파일 생성
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Photo App</title>
</head>
<body>
<h2> 사진 목록 페이지</h2>
<section>
<!-- 사진 여러장을 photos 라는 이름으로 가져와 photo 변수로 하나씩 불러옴 -->
{% for photo in photos %}
<div>
<h2>
<!-- photo.title로 해당 photo의 제목을 불러옴 -->
<a href="">{{photo.title}}</a>
</h2>
<!-- photo.image로 해당 photo의 이미지를 불러옴 -->
<img src="{{photo.image}}" width="50%">
<!-- 해당 photo의 author, description을 불러옴 -->
<!-- 밑의 detail을 생각해 주석처리 했다. -->
<p>{{photo.author}}</p>
<p>{{photo.description}}</p>
</div>
{% endfor %}
</section>
</body>
</html>
from django.shortcuts import render
# 우선 models.py에서 photo를 가져온다.
from .models import Photo
# 사진 목록
def photo_list(request):
# photo.object.all()을 통해 photo 모델 데이터를 모두 가져와 {}에 넣어 템플릿으로 전달
photos = Photo.objects.all()
return render(request, 'photo/photo_list.html', {'photos': photos})
from django.urls import path
from . import views
urlpatterns = [
path('', views.photo_list, name="photo_list"),
]
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('photo.urls')),
]
결과 미리 보기
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Photo App</title>
</head>
<body>
<h1>{{photo.title}}</h1>
<section>
<div>
<img src="{{photo.image}}" alt="{{photo.title}}" width="50%">
<p>{{photo.description}}</p>
<p>{{photo.author}}</p>
</div>
</section>
</body>
</html>
from django.shortcuts import render, get_object_or_404
from .models import Photo
# 세부 화면
# pk는 모델의 데이터를 구분하는 변수
def photo_detail(request, pk):
# 찾는 데이터가 없는 경우 404에러를 변환하는 함수
photo = get_object_or_404(Photo, pk=pk)
return render(request, 'photo/photo_detail.html', {'photo': photo})
from django.urls import path
from . import views
urlpatterns = [
path('', views.photo_list, name="photo_list"),
path('photo/<int:pk>/', views.photo_detail, name="photo_detail"),
]
{% for photo in photos %}
<div>
<h2>
<!-- url을 연결해주고 pk를 이용해 사진을 구분했다. -->
<a href="{% url 'photo_detail' pk=photo.pk %}">{{photo.title}}</a>
</h2>
<img src="{{photo.image}}" width="50%">
<p>{{photo.author}}</p>
<p>{{photo.description}}</p>
</div>
{% endfor %}
결과 미리 보기
Form (폼)
사용자가 데이터를 입력해 서버로 보내도록 도와주는 양식
사용자 = 양식을 채우고 POST방식으로 요청을 보냄
서버 = 해당 요청을 받아 처리함csrf_token
폼에 숨어있는 악의적인 코드로 사용자가 원하지 않는 글을 작성하는 보안 취약점을 방지 하기 위한 보안 토큰
CSRF (Cross-Site Request Forgery, 크로스 사이트 요청 위조)
사용자가 서버에 요청을 보내는데, 이 요청을 의도치않은 요청으로 만들어 서버로 보내는 공격
서버에서 랜덤한 값을 생성하여 response에 포함하여 전달되고,
사용자 세션 정보와 연관되어 서버에 전송하고 서버는 토큰과 세션의 유효성을 검사해 처리
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Photo App</title>
</head>
<body>
<h1><a href="/"> 홈으로 돌아가기 </a></h1>
<div>
<section>
<h2>New Photo</h2>
<form method="POST">
{% csrf_token %} {{form.as_p}}
<button type="submit">완료</button>
</form>
</section>
</div>
</body>
</html>
Form 태그 데이터 전송 방법(method)
1. GET
- 입력한 데이터를 url에 붙여 전송. 데이터가 다 보여서 보안에 취약
- 전송속도는 post방식보다 빠름
- 페이지 이동시 파라미터 전송, 검색결과 등 간단하고 보안이 필요하지 않은 경우 사용
2. POST
- 입력한 데이터를 본문안에 포함해서 전송
- 입력한 데이터가 URP에 보이지않아 GET방식보다 보안에 우수
- 로그인, 회원가입 등 보안이 필요하거나 복잡한 형태의 데이터를 전송하라 경우 사용
photo/forms.py 생성
폼 작성 (photo/froms.py)
from django import forms
from .models import Photo
class PhotoForm(forms.ModelForm):
class Meta:
model = Photo
fields = ('title', 'author', 'image', 'description')
from django.shortcuts import render, get_object_or_404, redirect
from .models import Photo
from .forms import PhotoForm
# 작성 화면
def photo_post(request):
if request.method == "POST":
form = PhotoForm(request.POST)
# form에 맞춰 잘 작성된 데이터인지 검사
if form.is_valid():
photo = form.save(commit=False)
# DB에 해당 데이터가 저장됨
photo.save()
return redirect('photo_detail', pk=photo.pk)
else:
form = PhotoForm()
return render(request, 'photo/photo_post.html', {'form': form})
from django.urls import path
from . import views
urlpatterns = [
path('', views.photo_list, name="photo_list"),
path('photo/<int:pk>/', views.photo_detail, name="photo_detail"),
path('photo/new/', views.photo_post, name="photo_post"),
]
<body>
<h2> 사진 목록 페이지</h2>
<h3><a href="{% url 'photo_post' %}">New Photo</a></h3>
결과 미리 보기 >> post와 같지만 이미 폼이 채워져있다.
작성 기능 템플릿 사용
- 비워져있는 폼에 데이터만 채우면 수정기능이 되므로 작성 기능과 템플릿 동일
뷰 작성 (photo/views.py)
- 뷰도 작성기능과 유사
# 수정 화면
def photo_edit(request, pk) :
photo = get_object_or_404(Photo, pk=pk)
if request.method == "POST":
form = PhotoForm(request.POST, instance=photo)
if form.is_valid():
photo = form.save(commit=False)
photo.save()
return redirect('photo_detail', pk=photo.pk)
else:
form = PhotoForm(instance=photo)
return render(request, 'photo/photo_post.html', {'form':form})
from django.urls import path
from . import views
urlpatterns = [
path('', views.photo_list, name="photo_list"),
path('photo/<int:pk>/', views.photo_detail, name="photo_detail"),
path('photo/new/', views.photo_post, name="photo_post"),
path('photo/<int:pk>/edit/', views.photo_edit, name="photo_edit"),
]
<body>
<h1>{{photo.title}}</h1>
<h3><a href="{% url 'photo_edit' pk=photo.pk %}">Edit Photo</a></h3>