한 걸음씩

[Django] ORM with view 2 본문

Django

[Django] ORM with view 2

winter17 2023. 3. 30. 11:53

1. HTTP request methods

  • CREAT : 게시글 작성 후 작성 완료를 나타내는 페이지를 렌더링 하는 것
  •  
  • 따라서 데이터 저장 후 유저를 어디론가 다시 보내야 한다 → 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 %}

게시글 생성 후 개발자 도구를 사용해 Form Data가 전송되는 모습 확인

⎣ 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