-
django update-review with axiosProject using python/Cloning Airbnb 2021. 3. 18. 09:10
url 설정
config/urls.py
urlpatterns = [ path("reviews/", include("reviews.urls", namespace="reviews")) ]
reviews/urls.py
from django.urls import path from reviews import views app_name = "reviews" urlpatterns = [ path("<int:room_pk>/<int:review_pk>/update/", views.updateReview, name="update") ]
Client
review.html
<div class="grid grid-cols-2 gap-x-52 gap-y-3 mb-10"> {% for review in room.reviews.all %} <div> <div class="flex justify-between items-center"> <div class="flex items-center mb-4"> {% if review.user.avatar %} <a href="{% url 'users:profile' review.user.pk%}"> <img src="{{review.user.avatar.url}}" class="img w-16 h-16 mr-4" alt="User avatar" title="User Avatar"> </a> {% else %} <a href="{% url 'users:profile' review.user.pk%}"> <div class="img w-16 h-16 mr-4">{{review.user.first_name|first|upper}}</div> </a> {% endif %} <div class="flex flex-col"> <span class="font-bold">{{review.user|capfirst}}</span> <span class="text-sm text-gray-400">{{review.created}}</span> </div> </div> {% if review.user == user %} <div class="w-24"> <button class="reviewAmend review_button bg-blue-600 mt-0">Update</button> <button id="reviewDelete" class="review_button bg-red-600 mt-3">Delete</button> </div> {% endif %} </div> <p class="mb-4 font-normal" name="{{review.pk}}">{{review.review}}</p> </div> {% endfor %} </div>
assets/js/updateReview.js
django는 form을 post로 server에 submit할 때 무조건 csrf token이 필요하다. .html file에서는 {% csrf_token %}을 추갛면 되지만 JS에서 axios로는 그것이 불가능하다. axios를 이용해서 form을 제출하고 싶다면 다음과 같이 axios.defaults.xsrfCookeName과 axios.defaults.xsrfHeaderName을 추가해줘야 한다.
import axios from "axios"; axios.defaults.xsrfCookieName = "csrftoken"; axios.defaults.xsrfHeaderName = "X-CSRFToken"; const reviewAmends = document.querySelectorAll(".reviewAmend"); const handleAmendInput = (event) => { event.preventDefault(); const room_pk = window.location.href.split("/")[4]; const form = event.target; const p = form.parentNode; const updateBtn = p.previousSibling.previousSibling.childNodes[3].childNodes[1]; const reviewNode = p.parentNode; const textarea = form.querySelector("textarea"); const text = textarea.value; const review_pk = reviewNode.id; p.innerHTML = text; updateBtn.addEventListener("click", handleAmend); updateBtn.classList.remove("hidden"); axios({ method: "POST", url: `/reviews/${room_pk}/${review_pk}/update/`, data: { review: text, }, }); }; const handleAmend = (e) => { const btn = e.target; const btnParent = btn.parentNode.parentNode; const p = btnParent.nextSibling.nextSibling; const form = document.createElement("form"); const textarea = document.createElement("textarea"); const div = document.createElement("div"); const submit = document.createElement("button"); btn.removeEventListener("click", handleAmend); btn.classList.add("hidden"); textarea.value = p.innerText; textarea.classList.add( "w-full", "h-20", "mb-2", "resize-none", "border", "border-black", "p-1", "rounded-lg" ); p.innerText = ""; div.classList.add("flex", "justify-end"); submit.innerText = "Amend"; submit.classList.add("review_button", "w-32", "bg-blue-600"); div.append(submit); form.appendChild(textarea); form.appendChild(div); p.appendChild(form); p.childNode = form; form.addEventListener("submit", handleAmendInput); }; const init = () => { if (reviewAmends) { reviewAmends.forEach((reviewAmend) => { reviewAmend.addEventListener("click", handleAmend); }); } }; init();
FBV(Function Based View)
reviews/views.py
django에서 Client가 전달하는 post 값은 request.POST.get()으로 받을 수 있는데 request.POST는 form-encoded data만 가능하다. JSON 형식으로 request가 오면 request.body를 사용해야 한다. 먼저 json을 import하고 json.loads()를 통해서 문자열로온 json을 dict으로 바꿔주자. 참고로 server에서 client로 보낼 때 직렬화 과정을 거치는데, 이 때는 json.dumps()를 사용해서 dict을 string으로 직렬화한다. json.loads는 직렬화 된 json을 다시 dict로 바꿔주는 method다.
# reviews/views.py import json from django.shortcuts import redirect, reverse from django.contrib import messages from django.http import HttpResponse from reviews import models as review_models from reservations import models as reservation_models def updateReview(request, room_pk, review_pk): review = review_models.Review.objects.get_or_none(pk=review_pk) if review is None: messages.error(request, "Review doesn't exist") content = json.loads(request.body.decode("utf-8")) text = content["review"] review.review = text review.save() return HttpResponse(200)
참고 자료
- 노마드 코더의 Airbnb 클론 강의
- django + axios에서 CSRF token 설정하기
- axios가 전달한 post 값을 수신하는 방법
소스 코드
github.com/zpskek/airbnb-clone-v3/commit/86d27058d4ed507d8ed0f00addb62f4c6df9baaa
'Project using python > Cloning Airbnb' 카테고리의 다른 글
django toggle-list by FBV (0) 2021.04.23 django delete-review by FBV with axios (0) 2021.03.18 django create-review by FBV (0) 2021.03.18 django cancel reservation by FBV (0) 2021.03.17 django confirm reservation by FBV (0) 2021.03.17