Django - Vue(Mixin 사용하기, bootstrap 팝업창 만들기 , 4)
Project/Django & Vue.js

Django - Vue(Mixin 사용하기, bootstrap 팝업창 만들기 , 4)

뉴비뉴 2019. 9. 4.

Mixin 사용하기

 

한개의 템플릿 내에 CreateView의 영역이 있고, ListView의 영역이 있다.

두 개의 제네릭뷰를 한 개로 조합하는 믹스인 기능이 필요하다.

 

체크해야 할 점은 View에서 넘겨주는 Context변수가 뭔지 확인해야 한다.

CreateView 에서는 따로 Context로 넘겨주는 값이 없고, ListView에서는 object_list를 넘겨준다.

 

위 점을 기억하고 View를 생성해보자.

class TodoMOMCV(ListView, CreateView): # (mixin, main)
	template_name = 'todo/todo_form_list.html'

여기서 중요한 점은 List와 Create View를 상속받을 때 순서도 중요하다는 것이다.

ccbv.co.uk 로 가면 CreateView가 더 복잡한 것을 확인할 수 있다.

왜냐하면 Form 처리 기능도 갖고 있기 때문이다.

다중상속을 받을 때 좀 더 복잡한 CreateView를 메인으로두고,

ListView를 Mixin으로 처리하는 것이 에러 발생 가능성을 없앨 수 있다.

 

mixin을 먼저 써주고, main 클래스를 나중에 써준다, 참고로 mixin이라는 단어의 의미가 메인재료에 첨가되는 첨가물을 의미한다.

 

# views.py

class TodoMOMCV(MultipleObjectMixin, CreateView):
    model = Todo # model은 Todo로 지정한다.
    fields = '__all__' # Todo model의 모든 필드를 가져와라
    template_name = 'todo/todo_form_list.html'
    success_url = reverse_lazy('todo:mixin') 

    def get(self, request, *args, **kwargs):
        self.object_list = self.get_queryset() # DB에서 레코드들을 꺼내오는 메소드get_queryset()
        # get_queryset() 메소드는 어느쪽에 있는 것을 호출할까? (MultipleObjectMixin, CreateView)
        # 이럴 때 순서가 중요하다, 앞에 있는 클래스를 먼저 봐서 이 클래스에 get_queryset 메소드가
        # 있다면 그걸 호출하고, 거기에 없으면 CreateView에서 찾아서 get_queryset() 메소드를 호출
        # 둘 다 get_queryset() 메소드가 있기 때문에 MultipleObjectMixin 에 있는 것이 호출된다.
        return super().get(request, *args, **kwargs)
        # 상위 클래스(TodoMOMCV)의 get 메소드를 그대로 호출하게 되면, CreateView클래스의
        # get_context_data 메소드가 호출되고, 이 메소드에서 object_list라는 context변수가
        # 템플릿에 넘어가게 되는 것이다.
        # 그리고 상위 클래스의 메소드를 오버라이딩 할 때는 인자는 동일하게 써줘야 한다.

    def post(self, request, *args, **kwargs):
        self.object_list = self.get_queryset()
        return super().post(request, *args, **kwargs) # 인자는 동일하게

 

bootstrap 팝업창 만들기

페이지 이동이 되지 않고 그 자리에서 팝업창을 띄워 삭제가 가능하게 해보자.

지금은 리스트에서 'x' 버튼을 누르면 get으로 confirm 페이지로 이동이되고, 거기서 삭제한다는 버튼을 누르면

post로 삭제가 이루어지고, list 페이지로 이동하게 되어있다.

 

해야할 작업은 'x' 버튼을 누르면 get 요청에 대한 작업은 생략하고 post 요청처리만 하게끔 만들어주자.

class TodoDelV2(DeleteView):
    model = Todo
    # template_name = 'todo/todo_confirm_delete.html' # form 을 보여주는 과정생략
    success_url = reverse_lazy('todo:mixin')

    def get(self, request, *args, **kwargs): # get 요청이 왔을 때
        return self.delete(request, *args, **kwargs) # 바로 삭제를 진행해라

VueOnly에서는 페이지 reloading이 일어나지 않지만, DjangoMixin에서는 페이지 reloading이 일어나고 있다.

이번에는 DjangoMixin 에서 삭제버튼을 눌렀을 때 정말로 삭제할 것인지 확인하는 팝업창을 만들도록 하겠습니다.

 

<!-- 삭제버튼 -->
<span class="removeBtn" data-toggle="modal" data-target="#myModal"
                  data-id="{{todo.id}}" data-name="{{todo.name}}" data-todo="{{todo.todo}}">&#x00D7</span>
                  
                  # data-id ~ data-name data-todo 로 해서 데이터를 넘겨준다.


<!-- Modal 팝업창 -->
    <div class="modal" id="myModal" tabindex="-1" role="dialog">
        <div class="modal-dialog" role="document">
            <div class="modal-content">
                <div class="modal-header">
                    <h5 class="modal-title" id="exampleModalLabel">Are you sure to delete ?</h5>
                </div>
                <div class="modal-body">
                    body-text
                </div>
                <div class="modal-footer">
                    <button type="button" class="btn btn-secondary btn-sm" data-dismiss="modal">Cancel</button>
                    <button type="button" class="btn btn-danger btn-sm">
                        <a href="">Delete</a></button>
                </div>
            </div>
        </div>
    </div>

</div>
{% endblock %}

{% block extra-script %} 
<script>
$('#myModal').on('show.bs.modal', function (event) {
    var button = $(event.relatedTarget)
    var id = button.data('id') <!-- 넘겨준 데이터를 받아서 저장 -->
    var name = button.data('name') <!-- 넘겨준 데이터를 받아서 저장 -->
    var todo = button.data('todo') <!-- 넘겨준 데이터를 받아서 저장 -->

    var modal = $(this)
    modal.find('.modal-body').text(name + '::: ' + todo)
    modal.find('.modal-footer a').attr('href', '/todo/' + id + '/delete2/')
})
</script>
{% endblock %}

  

댓글

💲 추천 글