장고 수정 기능 구현
이번에는 CRUD중 UPDATE에대한 기능을 구현해보겠습니다.
CRUD중 가장 어렵다고 알려진 UPDATE는 앞에서 배웠던 모든 기술을 총동원해야 한다고합니다.
구성하려는 페이지 구성은 다음과 같습니다.
페이지의 홈 화면에서는 create 버튼만 나타납니다.
상세보기 페이지를 누르게되면 update버튼이 나타납니다.
그 버튼을 클릭하면 사용자가 선택한 내용이 폼에 들어가있습니다.
글을 수정한 후 제출버튼을 누르면 변경사항이 서버에 전송되고, 변경된 topic의 상세보기 페이지로 이동하게됩니다.
상세보기 페이지에 들어가면 update 링크가 뜨게먼저 함수를 수정해보겠습니다.
아래와같이 HTMLTemplate을 수정해줍니다.
def HTMLTemplate(articleTag, id=None):
global topics
contextUI = ''
if id != None:
contextUI = f'''
<li>
<form action="/myapp/delete/" method="post">
<input type="hidden" name="id" value={id}>
<input type="submit" value="delete">
</form>
</li>
<li>
<a href="/myapp/update/{id}">update</a>
</li>
'''
ol = ''
for topic in topics:
ol += f'<li><a href="read/{topic["id"]}">{topic["title"]}</a></li>'
return f'''
<html>
<body>
<h1><a href="/myapp">Django</a></h1>
<ul>
{ol}
</ul>
{articleTag}
<ul>
<li><a href="/myapp/create/">create</a></li>
{contextUI}
</ul>
</body>
</html>
'''
아래와 같이 링크를 추가해 update링크로 접속할때 {id}값을 물고 들어가도록 구현하였습니다.
<a href="/myapp/update/{id}">update</a>
이제 저url을 받을수있도록 라우팅 설정을 해보겠습니다.
urls.py에 코드를 추가해보겠습니다.
from django.urls import path
from myapp import views
urlpatterns = [
path('', views.index),
path('create/', views.create),
path('read/<id>/', views.read),
path('update/<id>',views.update),
path('delete/',views.delete)
]
위와같이 path를 추가해 코드를 수정합니다.
이제 업데이트 함수를 구현해보겠습니다.
사용자가 GET으로 접속하면 UPDATE라는 텍스트를 출력해주고,
POST로 접근하면 상세보기 페이지로 이동하는 것부터 작성해보겠습니다.
아래와 같이 코드를 작성해줍니다.
@csrf_exempt
def update(request, id):
if request.method == 'GET':
article = 'Update'
return HttpResponse(HTMLTemplate(article, id))
elif request.method == 'POST':
return redirect(f'/myapp/read/{id}')
페이지를 로드해보면 Update텍스트가 정상적으로 출력되는것을 확인할 수 있습니다.
이제 Update UI를 만들어보겠습니다.
Update와 Create는 모두 글을 작성하는 폼이필요하므로 코드가 유사합니다.
하지만 Update는 기본적으로 UI안에 데이터가 들어가 있어야한다는 큰 차이점이 있습니다.
때문에 topics를 조회할 필요가있습니다.
그리고 조회에 성공했을때, 그 값을 selectedTopic = {”title”:topic[’title’]}을 통해 selectedTopic이라는 딕셔너리에 담겠습니다.
아래는 수정사항을 반영한 update함수 코드입니다.
@csrf_exempt
def update(request, id):
global topics
if request.method == 'GET':
for topic in topics :
if topic['id'] == int(id):
selectedTopic = {
"title":topic['title'],
"body":topic['body']
}
article = f'''
<form action="/myapp/update/{id}" method="post">
<p><input type="text" name="title" placeholder="title" value={selectedTopic["title"]}></p>
<p><textarea name="body" placeholder="body">{selectedTopic['body']}</textarea></p>
<p><input type="submit"></p>
</form>
'''
return HttpResponse(HTMLTemplate(article, id))
elif request.method == 'POST':
return redirect(f'/myapp/read/{id}')
페이지를 리로드 한 뒤 update링크를 누르면 선택한 글에해당하는 토픽이 폼에 채워진 것을 확인할 수 있습니다.
이제 서버로 전송된데이터로 topics변수의 값을 바꾸겠습니다.
먼저 title과 body를 변수로 뽑아내겠습니다.
그후 topics내의 일치하는 값을 뽑아냅니다.
일치한다면 값을 변경시켜줍니다.
그리고 그 과정이 성공했다면 사용자를 /myapp/read/{id} 으로 보내줍니다.
아래는 수정사항을 반영한 함수의 코드입니다.
@csrf_exempt
def update(request, id):
global topics
if request.method == 'GET':
for topic in topics :
if topic['id'] == int(id):
selectedTopic = {
"title":topic['title'],
"body":topic['body']
}
article = f'''
<form action="/myapp/update/{id}" method="post">
<p><input type="text" name="title" placeholder="title" value={selectedTopic["title"]}></p>
<p><textarea name="body" placeholder="body">{selectedTopic['body']}</textarea></p>
<p><input type="submit"></p>
</form>
'''
return HttpResponse(HTMLTemplate(article, id))
elif request.method == 'POST':
title = request.POST['title']
body = request.POST['body']
for topic in topics :
if topic['id'] == int(id):
topic['title']=title
topic['body']=body
return redirect(f'/myapp/read/{id}')
페이지를 로드해보겠습니다.
업데이트 링크를 눌러 내용을 수정한뒤 제출버튼을 누르면
위와같이 글의 제목과 내용이 수정되는것을 알 수 있습니다.
이제 CRUD의 꽃인 UPDATE구현을 완료하였습니다!