한 걸음씩
[Django] ORM with view 2 본문
1. HTTP request methods
- CREAT : 게시글 작성 후 작성 완료를 나타내는 페이지를 렌더링 하는 것
- 게시글을 '조회해줘'라는 요청이 아닌 '작성해줘'라는 요청이기 때문에 페이지 렌더링은 적절한 응답이 아님
- 2023.03.29 - [Django] - [Django] ORM with view
- 따라서 데이터 저장 후 유저를 어디론가 다시 보내야 한다 → redirect()
► redirect()
- 인자에 작성된 주소로 다시 요청을 보냄
- 페이지를 만든다는 개념이 아님! , 사용자가 index로 향할 수 있게 하는 주소일 뿐
# views.py
from django.shortcuts import render, redirect
def create(request):
# new에서 보낸 사용자 데이터를 받아서 변수에 할당
# print(request.GET)
title = request.GET.get('title')
content = request.GET.get('content')
# 저장 전에 유효성 검사와 같은 추가 작업을 위해 2번 방법을 택함
article = Article(title=title, content=content)
article.save()
# 결과 페이지 반환 - 데이터 전체 조회
# return render(request, 'articles/index.html)
# 이동할 주소(URL)를 사용자에게 응답
return redirect('articles:index')
# 생성한 글의 단일 조회(detail) 주소(url)로 이동 응답
return redirect('articles:detail', article.pk)
► HTTP
- 네트워크 상에서 데이터를 주고 받기위한 약속
- 요청과 응답
► HTTP request methods
- 데이터(리소스)에 어떤 요청(행동)을 원하는지를 나타내는 것 GET & POST
► 'GET' Method
- 특정 리소스를 조회하는 요청
- 길이 제한 O (255)
- GET으로 데이터를 전달하면 Query String 형식으로 보내짐
- http://127.0.0.1:8000/articles/create/?title=제목&content=내용
- 반드시 데이터를 가져올 때만 사용해야 함
► 'POST' Method
- 특정 리소스에 변경사항을 만드는 요청
- 글 생성, 수정, 삭제
- 길이 제한 X
- POST로 데이터를 전달하면 HTTP Body 에 담겨 보내짐
- POST method는 데이터베이스에 대한 변경사항을 만드는 요청이기 때문에 토큰을 사용해 최소한의 신원 확인을 하는 것
# views.py
def create(request):
# GET -> POST
title = request.POST.get('title')
content = request.POST.get('content')
# templates/articles/new.html
# GET -> POST
<form action="{% url 'articles:create' %}" method="POST">
≫ GET을 POST로 수정 후, new페이지에서 폼을 작성하고 제출하면 다음과 같은 오류 발생!
- HTTP response status code
- 특정 HTTP 요청이 성공적으로 완료되었는지 알려줌
- 5개의 그룹으로 나뉘어짐(1xx, 2xx, 3xx, 4xx, 5xx)
- 403 Forbidden
- 서버에 요청이 전달되었지만, 권한 때문에 거절되었다는 것을 의미
- CSRF token missing or incorrect
- [의미] CSRF token이 누락되었다
- CSRF
- Crodd-Site-Request-Forgery
- 사이트 간 요청 위조
- 사용자가 자신의 의지와 무관하게 공격자가 의도한 해동을 하여 특정 웹 페이지를 보안에 취약하게 하거나 수정, 삭제 등의 작업을 하게 만드는 공격 방법
- Security Token (CSRF Token)
- 대표적인 CSRF 방어 방법 (정상적인 유저인지 확인)
- 서버는 사용자 입력 데이터에 임의의 난수 값(token)을 부여
- 매 요청마다 해당 token을 포함시켜 전송 시키도록 함
- 이후 서버에서 요청을 받을 때마다 전달된 token이 유효한지 검증
# new.html
# form아래에 csrf_token 태그 생성
<form action="{% url 'articles:create' %}" method="POST">
{% csrf_token %}
⎣ DTL의 csrf_token 태그를 사용해 사용자에게 토큰 값을 부여
⎣ 요청 시 토큰 값도 함께 서버로 전송될 수 있도록 함
shell에서 수정, 삭제가 아니라, 화면에서 수정, 삭제!
2. DELETE
► Delete 로직 작성
# urls.py
from . import views
urlpatterns = [
path('<int:pk>/delete', views.delete, name='delete')
]
# views.py
def delete(requsest, pk):
# 삭제할 데이터 조회
# 왼쪽 pk : 기준 / 오른쪽 pk : 사용자(urls.py의 path <int:pk>)
article = Article.objects.get(pk=pk)
# 조회한 데이터 삭제(delete)
article.delete()
# 전체 조회 페이지 이동
return redirect('articles:index')
# detail.html
<body>
...
# POST 사용 이유 : 삭제하기 때문 (조회 외에는 POST)
# a 태그의 메서드는 GET이기때문에 조회할때만 사용 가능 (단순 페이지 이동때 사용)
<form action="{% url 'articles:delete' article.pk %}" method="POST">
{% csrf_token %}
<input type="submit" value = "DELETE"> # submit은 제출할 때
# button type="submit"과 동일함
</form>
<a href="{% url 'articles:index' %}">[back]</a>
</body>
3. UPDATE
- Update 로직을 구현하기 위해 필요한 view 함수
- edit : 사용자의 입력을 받는 페이지를 렌더링
- update : 사용자가 입력한 데이터를 받아 DB에 저장
► Edit 로직 작성
# urls.py
from . import views
app_name = 'articles'
urlpatterns = [
...
path('<int:pk>/edit/', views.edit, name='edit'),
]
# view.py
def edit(request, pk):
article = Article.objects.get(pk=pk)
context = {
'article': article,
}
return render(request, 'articles/edit.html, context')
# edit.html
<body>
<h1>EDIT</h1>
<form action="#" method="POST">
{% csrf_token %}
<div>
<label for="title">Title: </label>
<input type="text" name="title" id="title" value="{{ article.title}}"/>
# value는 수정 시 이전 데이터가 출력 될 수 있도록 처리
</div>
<div>
<label for="content">Content: </label>
<textarea name="content" id="content" {{ article.content }}></textarea>
# 수정 시 이전 데이터가 출력 될 수 있도록 처리 / textarea는 value가 없음
</div>
<input type="submit" />
</form>
<br />
<a href="{{% url 'articles:index %}}">[back]</a>
</body>
# detail.html
# edit 페이지로 이동하기 위한 하이퍼링크 작성
<a href="{{% url 'articles:edit' article.pk %}}">EDIT</a>
► Update 로직 작성
# urls.py
from . import views
app_name = 'articles'
urlpatterns = [
...
path('<int:pk>/updates/', views.update, name='update'),
]
# views.py
def update(request, pk):
# 수정 작업 과정
# 1. 데이터 조회
article = Article.objects.get(pk=pk)
# 2. 데이터 수정
# 2-1. 사용자가 입력한 form 데이터 저장
title = request.POST.get('title')
content = request.POST.get('content')
# 2-2. 조회한 데이터(article)의 필드 값 변경
article.title = title
article.content = content
# 3. 데이터 저장
article.save()
return redirect('articles:detail', article.pk)
# edit.html
<form action="{{% url 'articles:update' article.pk %}}" method="POST">
# 어떤 article을 update할건지 명시해야 함 -> article.pk
(UPDATE) articles/1/ : 1번 게시글 생성 할거야!
(DELETE) articles/1/ : 1번 게시글 삭제 할거야!
[주의] 코드를 외우지 말고 흐름을 기억할 것!!
'Django' 카테고리의 다른 글
[Django] Handling HTTP requests (0) | 2023.04.03 |
---|---|
[Django] Form (0) | 2023.04.03 |
[Django] ORM with view 실습 (0) | 2023.03.29 |
[Django] ORM with view (0) | 2023.03.29 |
[Django] ORM update / delete (0) | 2023.03.29 |