[멋사] Django - PhotoApp

김지연·2023년 5월 14일
0
post-thumbnail

<참고> 저번시간과 이어진다.

3. MTV 패턴으로 기능 구현

Template

사용자에게 보이는 부분으로 웹 페이지의 골격 = HTML로 작성된 부분
Django의 템플릿은 일반적인 HTML 작성과 거의 동일

템플릿 태그(Template Tag {% %})
HTML이 파이썬 코드로부터 데이터를 바로 넘겨받아 손쉽게 처리할 수 있는 도구
HTML은 마크업언어 -> 정적인 웹페이지 -> 자바스크립트
 
{}로 감싸는 형태로 for문, if문 같은 파이썬 기본 구문에 사용 가능
ex) {% endif %}

View

템플릿과 모델 사이를 이어주는 다리 역할
모델을 통해 데이터에 접근
-> 템플릿으로부터 요청받은 데이터 처리 후 템플릿으로 보냄
 
1. 프론트엔드가 백엔드에게 데이터 요청
2. 백엔드에서 데이터를 뽑아옴
3. 데이터 처리 후 프론트엔드에게 제공

URL

라우팅 역할과 동시에 서버로 해당 주소에 할당된 리소스를 요청하는 역할
리소스 => HTML페이지, 내부를 채우는 데이터도 포함


현 실습은 Model > Template > View > URL 순서로 작업한다.

01. 사진 목록 화면

결과 미리 보기

  1. photo/templates/photo 폴더 생성

  2. 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>
  1. 뷰 작성 (photo/views.py)
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})
  1. URL 연결 (photo/urls.py, photoWeb/urls.py)
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')),
]

02. 세부 정보 화면

결과 미리 보기

  1. photo_detail.html 파일 생성
<!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>
  1. 뷰 작성 (photo/views.py)
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})
  1. URL 연결 (photo/urls.py)
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"),
]
  1. 템플릿에 url 반영 (photo_list.html)
    {% 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 %}

03. 작성 기능

결과 미리 보기

Form (폼)

사용자가 데이터를 입력해 서버로 보내도록 도와주는 양식
사용자 = 양식을 채우고 POST방식으로 요청을 보냄
서버 = 해당 요청을 받아 처리함

csrf_token

폼에 숨어있는 악의적인 코드로 사용자가 원하지 않는 글을 작성하는 보안 취약점을 방지 하기 위한 보안 토큰

CSRF (Cross-Site Request Forgery, 크로스 사이트 요청 위조)

사용자가 서버에 요청을 보내는데, 이 요청을 의도치않은 요청으로 만들어 서버로 보내는 공격
서버에서 랜덤한 값을 생성하여 response에 포함하여 전달되고,
사용자 세션 정보와 연관되어 서버에 전송하고 서버는 토큰과 세션의 유효성을 검사해 처리

  1. photo_post.html 파일 생성
<!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방식보다 보안에 우수
- 로그인, 회원가입 등 보안이 필요하거나 복잡한 형태의 데이터를 전송하라 경우 사용

  1. photo/forms.py 생성

  2. 폼 작성 (photo/froms.py)

from django import forms
from .models import Photo


class PhotoForm(forms.ModelForm):
    class Meta:
        model = Photo
        fields = ('title', 'author', 'image', 'description')
  1. 뷰 작성 (photo/views.py)
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})
  1. URL 연결 (photo/urls.py)
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"),
]
  1. 템플릿에 url 반영 (photo_list.html)
<body>
<h2> 사진 목록 페이지</h2>
<h3><a href="{% url 'photo_post' %}">New Photo</a></h3>

04. 수정 기능

결과 미리 보기 >> post와 같지만 이미 폼이 채워져있다.

  1. 작성 기능 템플릿 사용
    - 비워져있는 폼에 데이터만 채우면 수정기능이 되므로 작성 기능과 템플릿 동일

  2. 뷰 작성 (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})
  1. url 작성
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"),
]
  1. 템플릿에 url 반영 (photo_detail.html)
<body>
  <h1>{{photo.title}}</h1>
  <h3><a href="{% url 'photo_edit' pk=photo.pk %}">Edit Photo</a></h3>

profile
천천히 꾸준히 하는 블로그

0개의 댓글