이번 시간에는 지난 시간에 이어 django에 대해 복습할 것이다!
우선 model을 작성하였으니 그 뒤로는 template, view, url을 작성해야 하는데 작성하기 전 각각 무슨 일을 하는지 알아보자.
template: HTML로 작성된 부분으로 사용자에게 보이는 웹 페이지 골격이다
{% template Tag %}: 템플릿 태그로 HTML이 파이썬 코드로 데이터를 바로 넘겨 받아 손쉽게 처리할 수 있는 도구이며 for, if문 같은 기본 구문에 사용이 가능하다
view: 템플릿과 모델 사이를 이어주는 역할 (프론트엔드 - 백엔드)
def 함수형 뷰와 class 클래스형 뷰가 존재한다
url: 라우팅 역할 + 서버로 해당 주소에 할당된 리소스를 요청하는 역할
작업 순서는 모델 > 템플릿 > 뷰 > URL 으로 진행할 것이다!
템플릿 파일을 만들기 위해 photo/templates/photo 폴더를 생성하고 photo_list.html 파일을 생성한다! 이때 templates 폴더에서 s를 빼먹으면 오류가 뜰 수도 있으니 스펠링에 주의하며 폴더와 파일을 만들자
그 뒤 photo_list.html 파일을 작성!
{% for photo in photos %}:
웹 페이지를 들어갔을 때 사진 목록이 보이게 하기 위해 템플릿 태그로 반복문을 작성해 사진 여러장을 photos 변수로 가져와 photo 변수로 하나씩 불러오도록 설정
{{photo.title}} :
models.py에서 작성한 title 값을 가져와 해당 photo의 제목을 불러옴
img src="{{photo.image}} width="50%" :
models.py에서 작성한 image 값을 가져와 photo의 이미지를 불러오도록 하였고,
크기는 너무 크게 보여지지 않도록 width 값을 50%로 줌
{{photo.author}}, {{photo.description}} :
models.py에서 작성한 photo의 author와 description을 불러옴
이제 템플릿 파일을 다 작성했으니 뷰 파일을 작성할 것이다!
현재 파일에 models.py에 있는 클래스 Photo를 호출하는 import값을 준 뒤 def 함수를 작성
사진 목록을 보여주는 photo_list 함수를 정의하고
템플릿 파일에서 적은 템플릿 태그 안의 photos를 사용해서 Photo의 모델 데이터를 모두 가져와 템플릿으로 전달한다
그리고 photo_list.html (템플릿파일)을 웹에 보여질 수 있도록 가공하는 렌더링 값을 return한다
이제 마지막으로 url 연결을 하기 위해 urls.py파일을 photo 폴더에 생성하고 밑에처럼 작성!
from . import views:
현재 폴더의 views.py를 호출하는 import 값을 줌
path( '' ) :
photo_list.html의 웹창의 주소 뒤에 올 값을 정하는데 사진 목록 창은 맨 처음 창이나 다름 없으므로 아무런 값을 넣지 않음
views.photo_list:
views.py 파일에서 방금 전 작성한 함수 photo_list를 호출
name = 'photo_list' :
이름을 photo_list로 설정한다고 생각하면 된다
그리고 photoWeb 폴더의 urls.py 파일에서도 작성!
include는 url을 계층적으로 관리하는 것으로 include('photo.urls') : 모든 url은 photo 폴더의 urls.py파일에서 담당한다는 의미이다!
이렇게 url까지 작성을 완료했다면 Terminal을 통해 runserver를 입력하면
이렇게 사진 목록이 뜨는 웹 페이지를 볼 수 있다! (맛있겠다)
물론 사진은 admin 페이지에 가서 photo에 사진을 추가해줘야 뜬다!
이제부터 이러한 방식으로 사진 정보 화면, 사진 작성 화면, 사진 수정 기능을 추가해 줄 것이다!
사진 목록 화면을 만들 때처럼 우선 템플릿 파일을 만든다
photo > templates > photo 폴더에 사진 정보 페이지를 보여줄 photo_detail.html 파일을 만들어준다!
코드 설명은 photo_list.html에서 설명했기 때문에 생략하겠다!
이렇게 템플릿 파일 (HTML)을 작성했으면 view와 url을 작성해준다!
pk: 모델의 데이터를 구분하는 변수
get_object_or_404(Photo, pk=pk):
Photo에서 찾는 데이터가 없는 경우 404 에러를 반환하는 함수
return 줄은 photo_list 함수에서 설명했기 때문에 생략하겠다!
urls.py에 detail 부분을 추가적으로 작성해준다.
photo/<int:pk>/ : 웹 페이지 주소 창 끝에 붙는 거라 생각하면 된다
이때 pk는 photo_detail 함수에서 정의했던 모델의 데이터를 구분하는 변수 값이므로
만약 모델의 데이터가 1이라면
이런 식으로 url 주소창을 설정하는 값이다!
나머지 코드들은 앞서 설명했기 때문에 생략하겠다!
자 이렇게 템플릿, 뷰, url까지 다 작성한 뒤 웹 페이지를 실행해서 이미지 상세 보기를 클릭하면 이상하게 클릭만 되고 상세보기 페이지로 넘어가지 않을 것이다!
당연하다! 왜냐하면 photo_list.html 템플릿 파일에서 photo_detail.html 템플릿 파일로 이동하는 값을 주지 않았기 때문이다!
이 값을 주기 위해 다시 photo_list.html 파일로 가서
밑줄 친 코드를 추가해서 사진 목록 페이지에서 photo.title (=포토 제목) 을 클릭했을 때 photo.detail.html 페이지가 나올 수 있도록 코드를 작성
그리고 다시 python manage.py runserver를 실행하면!
이렇게 이미지 제목을 클릭했을 때 photo.detail.html 파일처럼 웹 페이지가 나오는 걸 확인할 수 있다! (짝짝짝)
이전에 했던 것처럼 photo > templates > photo 폴더에 템플릿 파일을 만들어준다
이번에는 사진 작성하는 화면을 만들 것이기 때문에 photo_post.html 파일을 만들 것이다
form 태그 : 사용자가 입력한 데이터를 서버로 보내도록 도와주는 태그
(사진을 올리기 위해서는 사용자가 데이터를 입력해야 하고, 그 데이터를 보내야 하므로 form 태그를 사용한다!)
method = "POST" :
form 태그에서 데이터 전송 방법을 method라 하는데 이때 방법은 GET,POST가 있다
- GET: 사용자가 입력한 데이터를 URL에 붙여 전송
전송 속도가 빠르다는 장점
데이터 값이 다 보이기 때문에 보안에 취약하다는 단점
- POST: 사용자가 입력한 데이터를 본문안에 포함해 전송
로그인, 회원가입 등 보안이 필요한 부분과 복잡한 형태의 데이터를 전송할 때 사용
데이터 값이 URL에 보이지 않아 보안이 우수하다는 장점
GET보다는 속도가 느리다는 단점
주의할 점! : Django에서는 모든 POST 요청에 대해 CSRF토큰 검사를 해야 함
{% csrf_token %} :
{{form.as_p}} :
폼을 HTML p 태그를 사용하여 렌더링하도록 함
form
form.as_p
form.as_table
form.as_ul
등등
>> 어떤 HTML 태그로 래퍼(Wrapper)할 것인지 지정
그런데 우리는 현재 form 파일이 없으므로 이번에는 form 파일을 새로 만들 것이다
photo 폴더에 forms.py 파일을 생성!
django에서 기본적으로 제공하는 forms 을 상속받고
현재 파일에서 models 파일의 Photo 클래스 함수를 상속 받는다!
Class PhotoForm(forms.ModelForm):
PhotoForm이라는 이름을 가진 클래스 함수를 정의/ 필드 값을 입력으로 받는 폼 클래스
Class Meta :
메타라는 클래스를 PhotoForm 클래스 안에 작성하여 Photo의 title, author, image, description 입력을 PhotoForm 클래스가 받을 수 있도록 함
코드를 작성하면 빨간 밑줄이 생길 텐데, 그럴 때 마우스를 가져다대면 빨간 밑줄이 생긴 이유를 알려주는 메시지가 함께 나옴과 동시에 import 값이 필요한 거라면 pycharm에서 저절로 import 값을 추가해 준다! 이 기능을 애용하도록 하자 (편하다)
그래서 원래 views.py 파일에서 import 값이 추가 된 걸 확인할 수 있다
if request.metod == "POST" :
photo_post 함수에 들어온 request가 POST 요청이라면
(=사용자가 사진 작성을 했다는 의미)
form = PhotoForm(request.POST): 사용자가 작성한 사진의 폼 데이터를 form에 저장
if form.is_valid(): form에 저장된 데이터가 폼에 맞춰 제대로 작성된 것이라면 (django에서 제공하는 기본 기능)
photo = form.save(commit=False) : form의 데이터를 photo에 받아서
photo.save() : photo에 저장하고 (DB에 저장)
return redirect('photo_detail', pk=photo.pk) : 작성한 게시글의 사진 정보 화면으로 이동함, 이때 pk가 그냥 pk가 아닌 photo.pk인 이유는 기존에 있는 photo의 pk가 아니라 사용자가 새로 작성한 photo의 pk이기 때문이다
redirect: 다른 페이지로 이동시켜주는 함수
else: (들여쓰기를 잘 써야 한다) 사용자가 POST 요청을 보낸 게 아니라면
form = PhotoForm(): 새로 들어온 사용자이므로 폼 제공
return render(request, 'photo/photo_post.html', {'form':form} : 사진 작성을 할 수 있는 템플릿 파일과 form을 넘겨줘서 사용자가 사진 작성을 할 수 있는 화면을 제공
이제 url 파일에 가서
코드를 추가해 주고~
이번에도 메인 화면인 photo_list.html 파일에서 photo_post.html 화면으로 이동할 수 있게
밑줄친 코드를 추가하고 다시 runserver를 실행시키면!
'사진 올리기' 가 새로 생겼고 이곳을 클릭하면
사진을 새로 작성할 수 있는 웹 페이지가 뜬다!
올릴 사진의 정보를 작성하고 사진 올리기! 버튼을 누르면~
photo_detail 화면이 나옴과 동시에 입력한 사진 정보들이 뜬다!
그리고 홈으로 돌아가면 새로 작성한 사진이 추가된 것을 확인할 수 있다 > <
사진 수정 기능은 이미 있는 기존 폼에 데이터를 변경 혹은 작성을 하면 되기 때문에 템플릿 파일을 새로 작성하지 않고 기존의 photo_post.html 템플릿 파일을 사용한다!
그리고 views.py 파일에서 코드를 추가한다
photo_post 함수와 굉장히 비슷한데, 추가된 걸 살펴보자
photo = get_object_or_404(Photo, pk=pk) 앞에서 작성했던 코드인데,
여기서 사용되는 이유는 사진을 수정할 때 등록된 사진을 pk로 찾아오기 위해서다.
pk로 찾아올 수 없다면 404 에러를 발생한다!
instance = photo
수정 대상이 될 데이터 photo를 instance로 선정
else: form = PhotoForm(instance=photo)
POST 요청이 아닌 GET 요청이 들어오면 form에 photo 데이터를 담음
이제 url에 위와 같은 코드를 추가하고
이번에는 photo_list.html 가 아닌 photo_detail.html 에서 url 태그를 추가해 준다!
photo_detail.html 에서 추가하는 이유는 사진 정보를 수정하기 위해서는
사진 목록 화면 창보다는 사진 정보 창이 더 적합하기 때문이다.
이제 runserver를 실행하면
이렇게 글 수정하기 글씨가 뜨고~! 클릭하면!
이렇게 글 수정하는 창이 뜨면 성공이다!
글을 수정해서 사진 올리기! 버튼까지 클릭해서 수정이 완료됐다면 끝!
현재 조금씩 장고에 대한 이해가 생기고 재미도 붙이는 중이라서 이번 과제를 하면서 꽤 재미있었다! 물론 오류가 안 나서... 재미가 있었는지는 몰라도 ;)