[Vue-Django] axios

JeongChaeJin·2022년 9월 7일
0

Vue-Django

목록 보기
13/14

  • api는 보통 /api를 붙여준다.
  • 각각 View도 ListView, CreateView, DeleteView가 있지만 Base 기반 View가 코딩에 더 적합하다고 한다.

axios

this

created: function () {
            console.log("created()...");
            this.fetch_all_todo();
        },
        methods: {
            fetch_all_todo: function () {
                console.log("fetch_all_todo()...");

                var vm = this;
                axios.get('/api/todo/list/')
                    .then(function (res) {
                        console.log("GET RES", res);
                        vm.todoList = res.data;
                    })
                    .catch(function (err) {
                        console.log("GET ERR", err);
                    })
            },
  • Vue에서 this는 위치에 따라 그 의마가 다르니 유의해야된다.
    • 보통 this 는 Vue Object이지만, Callback 에서는 window객체다.
      • 강사님은 지역변수로 Vue 객체를 받아 값을 넣는 식으로 사용한다.
      • var vm = this; ... callback() 정의

JsonResponse

get

  • data, safe 인자가 중요하다.

    • data : dict, list
    • data가 dict, list가 아니면 safe = False
  • Django에서 response를 날려주면, Vue는 res.data로 받으면 된다.

    • res는 response object
  • ListView는 기본적으로 HTTP Response를 보낸다. Json Response로 바꿔주려면 어떻게 해야되나 ?

  • ListView의 get method를 보면 self.render_to_response(context)를 return 하고 있다.

  • render_to_reponse method를 살펴보면 self.reponse_class를 return 하고 있다. 이것이 바로 HTTP Response이므로 Json Response로 조작하기 위해서는 이 method를 overriding 해야된다.
    def render_to_response(self, context, **response_kwargs):
        todoList = list(context['object_list'].values())
        return JsonResponse(data=todoList, safe=False)

  • get method의 Flow를 살펴보면, get_query_set()으로 object_list 멤버 변수를 얻어온다.

  • get_queryset() method를 보면, self.model._default_manager.all() 부분이 해당 모델에 대한 all DB를 불러오는 것이다.

  • get_context_data() method를 보면 context에 object_list라는 key에 queryset이 mapping 되는 것을 알 수 있다.

  • 즉, response 시 전달되는 object_list 는 context 변수에 매핑되어있다.
    def render_to_response(self, context, **response_kwargs):
        todoList = list(context['object_list'].values())
        return JsonResponse(data=todoList, safe=False)
  • 따라서 오버라이딩을 위의 context의 object_list(dict) 의 values()로 값을 꺼내서 JsonResponse 로 return 하면된다.
  • 값이 dict가 아니므로 safe 인자를 False로 한다.
  • queryset은 values() 사용 시, dictionary로 매핑된다.

delete

remove_todo: function (todo, index) {
                console.log("remove_todo()...", index);
                if (confirm("Really delete ?") == false) return;

                var vm = this;
                axios.delete('/api/todo/' + todo.id + '/delete/')
                    .then(function (res) {
                        console.log("DELETE RES", res);
                        vm.todoList.splice(index, 1);
                    })
                    .catch(function (err) {
                        console.log("DELETE ERR", err);
                    })
            },
  • Delete 요청이 성공 하면 vue 상에서의 data에서도 삭제, Backend(Django) 에서도 삭제
path('todo/<int:pk>/delete/', views.ApiTodoDelV.as_view(), name='delete'),
  • urls.py
# @method_decorator(csrf_exempt, name='dispatch')
class ApiTodoDelV(BaseDeleteView):
    model = Todo

    def delete(self, request, *args, **kwargs):
        self.object = self.get_object()
        self.object.delete()
        return JsonResponse(data={}, status=204)
  • views.py

  • 해당 ccbv 에서 확인해보면 delete method를 오버라이딩 해야하는 것을 알 수 있다.

    • 참고해서 오버라이딩 후 JsonResponse 객체를 return 해주면 된다.
  • Django에서는 csrf 방어를 제공해주고 있다.

  • ajax 계열의 경우 위 사진 처럼 예시를 제시하고 있다.

# @method_decorator(csrf_exempt, name='dispatch')

  • 위코드에서 해당 데코레이터는 csrf_exempt로 csrf 방어가 필요없을 때 클래스형 뷰에 사용하는 데코레이터다. 테스트시에만 사용했다.
  • DeleteView는 Template 관련 클래스르 상속 받고 있는데, 템플릿 처리가 필요없는 경우 Base 뷰클래스를 상속받는게 좋기 때문에 Base류 View를 상속받고 있음에 유의한다.

post

add_todo: function () {
                console.log("add_todo()...");
                if (this.todo == '') return;
                if (this.name == '') this.name = '홍길동';

                var vm = this;
                var postData = {name: this.name, todo: this.todo};
                axios.post('/api/todo/create/', postData)
                    .then(function (res) {
                        console.log("POST RES", res);
                        vm.todoList.push({id: res.data.id, name: res.data.name, todo: res.data.todo});
                    })
                    .catch(function (err) {
                        console.log("POST ERR", err)
                    })
                this.name = this.todo = '';
            },
  • vue
path('todo/create/', views.ApiTodoCV.as_view(), name='create'),
  • urls
# @method_decorator(csrf_exempt, name='dispatch')
class ApiTodoCV(BaseCreateView):
    model = Todo
    fields = '__all__'

    def get_form_kwargs(self):
        kwargs = super().get_form_kwargs()
        kwargs['data'] = json.loads(self.request.body)
        return kwargs

    def form_valid(self, form):
        print("form_valid()", form)
        self.object = form.save()
        newTodo = model_to_dict(self.object)
        print(f"newTodo: {newTodo}")
        return JsonResponse(data=newTodo, status=201)

    def form_invalid(self, form):
        print("form_invalid()", form)
        print("form_invalid()", self.request.POST)
        print("form_invalid()", self.request.body.decode('utf8'))
        return JsonResponse(data=form.errors, status=400)
  • axios로 전달하면, Django에서 request.POST가 아니라. request.body로 온다.
    • Django docs에 있음. HTTP Reponse 쪽
  • kwargs의 data에 js의 string 으로 들어온 body를 json loads를 통해 dict로 변환해준다.
    = form_valid도 self.object가 model이므로 model_to_dict function을 통해서 dict로 바꿔 JsonResponse로 보내준다.
  • form_invalid는 django docs를 보는게 좋고, 에러내용을 Dict로 보내주는 역할이다.
profile
OnePunchLotto

0개의 댓글