일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- git
- 스파르타내일배움캠프
- github
- sort
- programmers
- 내일배움캠프
- greedy
- java
- 스파르타내일배움캠프TIL
- 자바
- 알고리즘
- Django
- 탐욕알고리즘
- drf
- SQL
- 코딩테스트준비
- 백준
- 파이썬
- API
- 코딩테스트
- 롤
- 장고
- Riot
- 라이엇
- 그리디알고리즘
- python
- 리그오브레전드
- 그리디
- lol
- 프로그래머스
- Today
- Total
Lina's Toolbox
Django MTV 사용하기 RUD (Read, Update, Delete) 본문
Django MTV 사용하기 RUD (Read, Update, Delete)
Woolina 2024. 8. 30. 15:22
보통 글작성하면 이화면이 나오지는 않죠?
- 글을 작성한 뒤 글 목록 페이지를 보여주도록 수정해볼까요?
→ 아 ! 그러면 /create/ 경로에서 create.html 을 랜더링하는게 아니라 articles.html 을 랜더링하면 되지!
…. ?
- 글목록 어디갔지?
- url은 왜 /articles/create/ 지?
→ html만 다른 템플릿으로 랜더링 했을뿐, 실제로 url이 이동해서 GET 요청을 보낸 것이 아닙니다!
→ 단순히 랜더링 해주는게 아니라, 리다이렉트(내가 지정한 url로 돌려보내는 것)를 해줘야한다.
redirect 사용하기
- redirect는 지정한 URL로 되돌리는 것을 말합니다.
- 우리가 웹 사이트를 이용하면서 많이 봐왔던 동작 방식입니다.
articles/views.py
from django.shortcuts import render, redirect
...
def create(request):
title = request.POST.get("title")
content = request.POST.get("content")
article = Article(title=title, content=content)
article.save()
return redirect("articles")
redirect()함수 import 필요
view.py 에서 def create()를 다 돈 후,
view.py의 articles로 가서
articles의 코드를 실행하는것!!
💡 PRG 패턴
이러한 패턴을 PRG(Post-Redirect-Get)패턴이라고 합니다.
POST요청을 서버에서 처리하고 서버에서는 다른 주소로 Redirect하도록 응답하고 브라우저는 GET방식으로 서버를 호출하여 사용자의 요청이 반영된 것을 보여줍니다.
게시글 작성후 제출 버튼을 눌렀을 때 화면이 이동되지 않는다면 제출 버튼을 여러번 누를 수가 있겠죠?
그러면 중복된 게시글이 작성될 수 있습니다.
PRG패턴을 사용하면 반복적인 POST호출을 막을 수 있고 사용자의 입장에서도 처리가 끝나고 처음 단계로 돌아간다는 느낌을 주게 됩니다.
상세페이지 조회하기
지금까지 우리가 설계한 URL구조는 이렇습니다.
- /articles/ → 전체 글 목록 페이지
- /articles/new/ → 글 작성 페이지
- /articles/create/ → 실제 글 추가 로직
→ 뭔가 허전하지 않으신가요? 게시글을 생성했다면?? 게시글을 클릭해서 읽어볼 수도 있어야겠죠? ☝️
→ 맞습니다! 글 상세페이지를 위한 URL을 추가해봅시다!
구현하기
(detail) articles/urls.py
from django.urls import path
from . import views
urlpatterns = [
path("", views.articles, name="articles"),
path("<int:pk>/", views.article_detail, name="article_detail"),
path("new/", views.new, name="new"),
path("create/", views.create, name="create"),
...
]
(detail) articles/views.py
def article_detail(request, pk):
article = Article.objects.get(pk=pk)
context = {
"article": article,
}
return render(request, "article_detail.html", context)
articles/templates/article_detail.html
{% extends "base.html" %}
{% block content %}
<h2>글 상세 페이지</h2>
<p>제목: {{ article.title }}</p>
<p>내용: {{ article.content }}</p>
<p>작성일시: {{ article.created_at }}</p>
<p>수정일시: {{ article.updated_at }}</p>
<a href="{% url 'articles' %}">목록 보기</a>
{% endblock content %}
추가 작업
- 자 이렇게 해서 상세페이지도 불러올 수 있게 되었습니다.
- 저희는 리다이렉트도 배웠고 게시글 상세페이지URL도 설계했으니 게시글 작성후 상세페이지로 리다이렉트시키는 걸 구현해봅시다.
articles/views.py
def create(request):
title = request.POST.get("title")
content = request.POST.get("content")
article = Article(title=title, content=content)
article.save()
return redirect("article_detail", article.id)
편의성 업데이트
- 프로젝트 편의성 업데이트를 해볼까요?
- 프로젝트에서 불편한 점을 찾아봅시다.
- 새로운 글을 작성하려면 브라우저 주소창에 /new/경로를 입력해서 작성해야된다.
- 게시글 작성페이지에서 게시글 목록 페이지로 이동할 수 있는 링크가 있으면 좋겠다.
- 본문이 바로 보인다.(지금은 본문이 짧지만 본문이 500줄, 1000줄 정도 되면 다른 게시물을 보기가 힘들 것 같네요 😮💨)
articles/articles.html
{% extends "base.html" %}
{% block content %}
<h1>Articles</h1>
<a href="{% url 'new' %}">새 글 작성</a>
<ul>
{% for article in articles %}
<li>
<a href="{% url 'article_detail' article.id %}">
<div>[{{ article.id }}] {{ article.title }}</div>
</a>
<br>
</li>
{% endfor %}
</ul>
{% endblock content %}
articles/new.html
<a href="{% url 'articles' %}">목록으로</a>
💡 편의성 업데이트
1. 글 작성 링크 만들기 ✅
2. 게시글 작성 페이지에 게시글 목록 페이지로 이동할 수 있는 링크 만들기 ✅
3. 글 제목만 보여주고 글제목을 클릭하면 상세페이지로 이동하기 ✅
글 삭제하기
- 게시글 삭제도 구현해봅시다.
- 구현
- 글 삭제 로직을 진행하는 url 만들기
- 글 삭제하는 view 만들기
- 삭제하고자 하는 글 가져오기
- 글 삭제
- 삭제한다음 이동할곳으로 redirect
- 글 삭제 버튼 만들어주기
(delete) articles/urls.py
path("<int:pk>/delete/", views.delete, name="delete"),
(delete) articles/views.py
def delete(request, pk):
article = Article.objects.get(pk=pk)
article.delete()
return redirect("articles")
삭제 버튼 만들기
글삭제 버튼은 어떻게 만들면 좋을까? 또 a태그?
NO! a태그는 누르면 해당 url로 GET 요청을 보내는 것!
- 삭제라는 것도 결국에는 데이터베이스를 조작하는 요청 !
- → POST 방식으로 요청해야함
- 따라서→ form 사용
(delete) articles/detail.html
{% extends "base.html" %}
{% block content %}
<h2>글 상세 페이지</h2>
<p>제목: {{ article.title }}</p>
<p>내용: {{ article.content }}</p>
<p>작성일시: {{ article.created_at }}</p>
<p>수정일시: {{ article.updated_at }}</p>
<a href="{% url 'articles' %}"><button>목록 보기</button></a>
<hr>
<form action="{% url 'delete' article.pk %}" method="POST">
{% csrf_token %}
<input type="submit" value="글삭제">
</form>
{% endblock content %}
💡 엇 그런데 말입니다?
127.0.0.1:8000/articles/3/delete/ 를 직접 입력해서 들어가면 어떻게 될까요?
→ 삭.제.된.다
→ 왜?
→ 로직에 이상이 없으니까 !
- 위 URL로 GET 요청이 들어오면
- view에서 처리하니까
- 삭제된다
- 이렇게 url로 임의로 글 삭제가 가능해져버리면 안되겠죠? 수정해봅시다!
요청방식이 POST인 경우만 삭제하도록 수정
- [코드스니펫] (POST인 경우에만 삭제)articles/views.py
def delete(request, pk):
article = Article.objects.get(pk=pk)
if request.method == "POST":
article.delete()
return redirect("articles")
return redirect("article_detail", article.pk)
post 요청일 경우에만 삭제처리 하고 아닐경우(get 요청 등)엔 그냥 상세페이지를 보여주게 수정
글 수정하기
- 글을 수정하는 로직을 생각해 봅시다.
- 글 수정하는 url 만들기
- 수정할 글을 보여주는 url
- 글 수정을 처리할 url
- 글 수정하는 로직을 수행하는 view 만들기
- 수정할 글을 보여주는 view
- 글 수정을 처리하는 view
- 글 수정을 수행하는 template 만들기
- 글 수정 버튼 만들기
- 글 수정하는 url 만들기
💡 전체 흐름
- 글 수정하는 url 만들기
- 수정할 글을 보여주는 url (articles/<pk>/edit/)
- 글 수정을 처리할 url(articles/<pk>/update/)
- 글 수정하는 로직을 수행하는 view 만들기
- 수정할 글을 보여주는 view (edit view)
- 글 수정을 처리하는 view (update view)
- 글 수정을 수행하는 template 만들기 (edit.html)
- 글 수정 버튼 만들기 → detail 페이지에 만들어주기
(edit) articles/urls.py
path("<int:pk>/edit", views.edit, name="edit"),
(edit) articles/views.py
...
def edit(request, pk):
article = Article.objects.get(pk=pk)
context = {
"article": article,
}
return render(request, "edit.html", context)
...
articles/templates/edit.html
{% extends "base.html" %}
{% block content %}
<h1>Update Article</h1>
<form action="{% url 'update' article.pk %}" method="POST">
{% csrf_token %}
<label for="title">제목</label>
<input type="text" name="title" id="title" value={{ article.title }}><br><br>
<label for="content">내용</label>
<textarea name="content" id="content" cols="30" rows="10">{{ article.content }}</textarea><br><br>
<button type="submit">저장</button>
</form>
{% endblock content %}
(update) articles/urls.py
path("<int:pk>/update/", views.update, name="update"),
(update) articles/views.py
...
def update(request, pk):
article = Article.objects.get(pk=pk)
article.title = request.POST.get("title")
article.content = request.POST.get("content")
article.save()
return redirect("article_detail", article.pk)
...
(update) detail.html
<a href="{% url 'edit' article.pk %}"><button>글수정</button></a>
💡 수정하기 버튼은 a 태그일까 form일까?
수정하는 페이지로 넘어가는 화면은 데이터베이스의 조작이 없다.
데이터가있는 화면만 보여주는 것이다
→ form 태그가 아닌 a태그 사용하는 GET요청이다!
'스파르타 내일 배움 캠프 AI 웹개발 과정 > Django framework' 카테고리의 다른 글
Django의 URL namespace (0) | 2024.09.02 |
---|---|
Django Form (0) | 2024.08.31 |
Django MTV 사용하기 CR (Create, Read) (0) | 2024.08.29 |
dbdiagram.io: Django 프로젝트에서 ERD 자동으로 그려주는 사이트 (0) | 2024.08.27 |
Django ORM (0) | 2024.08.27 |