Board project - 5

[ Board project ]

  • AJAX

    • 비동기식 JavaScript와 XML(Asynchronos Javascript And XML)
    • JavaScript를 통해서 서버에 데이터를 요청
    • 서버에 로딩된 데이터를 페이지에 보여주기 위해 새로운 HTML 페이지로 가지 않음
    • ajax를 통해 주로 주고 받는 형태가 XML이나 JSON
  • 댓글 기능에 AJAX 적용하기

    1. 버튼을 통해 데이터 가져오기

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      # views.py에 추가

      """
      일반적인 경우 데이터를 전송하기 위해 json 사용
      """
      from django.http import JsonResponse
      def get_data_ajax(request):
      data = {
      "name":'Jake',
      "age":100,
      "bloodtype":"0",
      }
      return JsonResponse(data)


      # urls.py에 추가
      from .views import get_data_ajax
      urlpatterns = [
      path('ajax/get_data/', get_data_ajax, name='get_data_ajax'),
      ]
      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
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      61
      62
      63
      64
      65
      66
      67
      68
      69
      70
      71
      72
      73
      74
      75
      76
      77
      78
      79
      80
      81
      82
      83
      84
      85
      86
      87
      88
      89
      90
      91
      92
      93
      94
      95
      96
      97
      98
      99
      100
      101
      102
      <!--// board_project/layout/base.html //-->

      <!--//
      bootstrap JS 적용에서 3개의 Script 중에 첫번째 Script 교체 적용
      jQuery.com - Download - google CDN - jQuery/3.x snippet의 내용 작성
      //-->
      <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
      <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>


      <!--// board_project/board/templates/board/document_list.html //-->
      {% extends 'base.html' %}
      {% block title %}
      Document List
      {% endblock %}

      {% block content %}
      <div class="row">
      <div class="col"></div>
      <div class="col-12">
      <table class="table table-striped">
      {% for object in object_list %}
      <tr>
      <td>{{object.id}}</td>
      <td>{{object.title}}</td>
      <td>{{object.author.username}}</td>
      <td>{{object.updated}}</td>
      </tr>
      {% endfor %}
      </table>
      <!--// 데이터가 표시될 곳 지정 //-->
      <div class="data_area">
      데이터가 입력될 곳
      </div>
      <!--// url 연결 //-->
      <a href="{% url 'board:get_data_ajax' %}" class="btn_get_data btn btn-primary">데이터 가져오기</a>

      <nav aria-label="Page navigation example">
      <ul class="pagination justify-content-center">
      {% for page in page_range %}
      <li class="page-item"><a class="page-link" href="{% url 'board:list' %}?page={{page}}">{{page}}</a></li>
      {% endfor %}
      </ul>
      </nav>

      <form action="" method="get" id="search_form" class="">
      {%csrf_token%}
      <div class="form-row align-items-center justify-content-center">
      <div class="form-check form-check-inline">
      <input class="form-check-input" type="checkbox" name="search_type" id="inlineCheckbox1" value="author">
      <label class="form-check-label" for="inlineCheckbox1">작성자</label>
      </div>
      <div class="form-check form-check-inline">
      <input class="form-check-input" type="checkbox" name="search_type" id="inlineCheckbox2" value="title">
      <label class="form-check-label" for="inlineCheckbox2">제목</label>
      </div>
      <div class="form-check form-check-inline">
      <input class="form-check-input" type="checkbox" name="search_type" id="inlineCheckbox3" value="text">
      <label class="form-check-label" for="inlineCheckbox3">본문</label>
      </div>
      </div>
      <div class="form-row align-items-center justify-content-center">
      <div class="col-sm-3 my-1">
      <input type="text", class="form-control" placeholder="Search Keyword" name="search_key">
      </div>

      <div class="col-auto my-1">
      <button type="submit" class="btn btn-primary">Search</button>
      </div>
      </div>
      </form>
      </div>
      <div class="col"></div>
      </div>
      {% endblock %}
      {% block extra_script %}
      <script type="text/javascript">
      // 1. 버튼을 누르면 페이지 이동이 안되도록
      // 2. 데이터를 가져오기
      $(function(){
      // 페이지 로딩이 끝나면 할일들
      $('.btn_get_data').click(function(e){
      e.preventDefault(); // 버튼을 클릭하면 이동 못하게 기본 기능 취소
      //alert('clicked'); // 확인을 위해 알림창 띄우기
      url = $(this).attr('href');
      $.ajax({
      // ajax 호출이 사용할 매개변수
      url:url
      }).done(function(data){
      // 호출이 끝나면 받은 데이터를 처리하는 부분
      name = data.name;
      age = data.age;
      bloodtype = data.bloodtype
      //alert(data.bloodtype);
      html = "<ul><li>"+name+"</li><li>"+age+"</li><li>"+bloodtype+"</li></ul>";
      $('.data_area').html(html);
      });
      });
      });
      </script>
      {% endblock %}
    2. 댓글 기능에 ajax 적용

      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
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      61
      62
      63
      64
      65
      66
      67
      68
      69
      70
      71
      72
      73
      # views.py에 추가
      from django.template.loader import render_to_string

      def comment_create(request, document_id):
      # ajax 기능에 의해 호출된 것인지 구분하기 위한 값
      is_ajax = request.POST.get('is_ajax')

      document = get_object_or_404(Document, pk=document_id)
      comment_form = CommentForm(request.POST)
      comment_form.instance.author_id = request.user.id
      comment_form.instance.document_id = document_id
      if comment_form.is_valid():
      comment = comment_form.save()

      # 만약 ajax에 의해 호출되었다면 redirection없이 Json 형태로 응답
      if is_ajax:
      # 데이터를 만들어서 던져주기
      html = render_to_string('board/comment/comment_single.html',{'comment':comment})
      return JsonResponse({'html':html})

      return redirect(document)


      from django.contrib import messages

      def comment_update(request, comment_id):
      # GET과 POST를 구분
      is_ajax, data = (request.GET.get('is_ajax'), request.GET) if 'is_ajax' in request.GET \
      else (request.POST.get('is_ajax', False), request.POST)

      comment = get_object_or_404(Comment, pk=comment_id)
      document = get_object_or_404(Document, pk=comment.document.id)

      if request.user != comment.author:
      messages.warning(request, "권한 없음")
      return redirect(document)

      # ajax에 의해 호출될 때 응답
      if is_ajax:
      form = CommentForm(data, instance=comment)
      if form.is_valid():
      form.save()
      return JsonResponse({'works':True})

      if request.method == "POST":
      form = CommentForm(request.POST, instance=comment)
      if form.is_valid():
      form.save()
      return redirect(document)
      else:
      form = CommentForm(instance=comment)
      return render(request, 'board/comment/update.html', {'form':form})

      def comment_delete(request, comment_id):
      # GET과 POST를 구분
      is_ajax = request.GET.get('is_ajax') if 'is_ajax' in request.GET else request.POST.get('is_ajax', False)
      comment = get_object_or_404(Comment, pk=comment_id)
      document = get_object_or_404(Document, pk=comment.document.id)

      if request.user != comment.author and not request.user.is_staff and request.user != document.author:
      messages.warning(request, "권한 없음")
      return redirect(document)

      # ajax에 의해 호출될 때 응답
      if is_ajax:
      comment.delete()
      return JsonResponse({'works':True})

      if request.method == "POST":
      comment.delete()
      return redirect(document)
      else:
      return render(request, 'board/comment/delete.html', {'object':comment})
      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
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      61
      62
      63
      64
      65
      66
      67
      68
      69
      70
      71
      72
      73
      74
      75
      76
      77
      78
      79
      80
      81
      82
      83
      84
      85
      86
      87
      88
      89
      90
      91
      92
      93
      94
      95
      96
      97
      98
      99
      100
      101
      102
      103
      104
      105
      106
      107
      108
      109
      110
      111
      112
      113
      114
      115
      116
      117
      118
      119
      120
      121
      122
      123
      124
      125
      126
      127
      128
      129
      <!--// board_project/board/templates/board/document_detail.html //-->
      {% extends 'base.html' %}
      {% block title %}
      Document Detail
      {% endblock %}

      {% block content %}
      <div class="row">
      <div class="col"></div>
      <div class="col-6">
      {{object.title}} {{object.text}} {{object.image.url}} {{object.author.username}}<br>
      <hr>
      <!--// form에 id 추가 //-->
      <form action="{% url 'board:comment_create' object.id %}" method="post" id="comment_form">
      {% csrf_token %}
      <input type="hidden" name="is_ajax" value="">
      {{comment_form.as_p}}
      <input type="submit" value="Comment" class="btn btn-outline-primary">
      </form>
      <div id="docs_comment_list_area">
      {% include 'board/comment_list.html' %}
      </div>
      </div>
      <div class="col"></div>
      </div>
      {% endblock %}
      {% block extra_script %}
      <script type="text/javascript">
      // 댓글의 생성, 수정, 삭제에 대한 script 추가
      $(function() {
      // 1. 누구한테 이벤트를 설정할 것인가?
      // 2. 어떤 이벤트를 설정할 것인가?
      $('#comment_form').submit(function(e) {
      // alert('댓글 쓰기 완료');
      // 댓글 남기기
      $('input[name="is_ajax"]').val("1");
      url = $(this).attr('action');
      params = $(this).serialize(); // 전달해주는 데이터들을 하나로 합침
      $.ajax({
      url:url,
      method:"POST",
      data:params
      }).done(function(data) {
      // 댓글 입력창 내용 비우기
      $('#id_text').val("");
      $('#comment_list tbody').prepend(data.html); // tbody 시작 지점에 요소 끼워넣기
      // $('#comment_list tbody').append(tr); // tbody 끝 지점에 요소 끼워넣기
      // is_ajax 값 초기화
      $('input[name="is_ajax"]').val("");
      });
      return false;
      });

      $('.btn_comment_delete').click(function(e) {
      e.preventDefault();
      var input = confirm('댓글을 삭제하시겠습니까?');
      if (input==true) {
      alert('댓글을 삭제하였습니다.');
      // ajax 호출
      comment = $(this).parents('tr');
      url = $(this).attr('href')+"?is_ajax=1";

      $.ajax({
      url:url
      }).done(function(data) {
      if(data.works) {
      comment.remove(); // 해당 객체 지우기
      }
      });
      }
      });

      $('.btn_comment_update').click(function(e) {
      e.preventDefault();
      url = $(this).attr('href')+"?is_ajax=1";
      comment = $(this).parent().siblings('.comment_text'); // 원래 댓글을 찾음
      //text = prompt('수정될 댓글 내용을 입력하세요.', comment.text()); // 원래 댓글을 프롬프트로 보여줌
      //if(text==null) return false; // 입력 취소면 함수 종료
      input = "<input type='text' class='update_text' value='"+comment.text()+"'>";
      comment.html(input);
      $('.update_text').keypress(function(e){
      if(e.keyCode==13) { // 키보드 Enter에 대한 키 값 설정
      text = $(this).val();
      $.ajax({
      url:url,
      data:{
      text:text
      }
      }).done(function(data) {
      // 댓글 수정이 끝나면 할 일
      if(data.works) {
      comment.text(text);
      }
      });
      }
      });
      });
      });
      </script>
      {% endblock %}


      <!--// board_project/board/templates/board/comment_list.html //-->
      <!--// table에 id 추가//-->
      <table class="table table-strped" id="comment_list">
      <thead>
      <tr>
      <th colspan="3" class="align-left">댓글 목록</th>
      </tr>
      </thead>
      <tbody>
      {% for comment in comments %}
      <!--// include를 통해 겹치는 구문 제거 //-->
      {% include 'board/comment/comment_single.html' %}
      {% endfor %}
      </tbody>
      </table>


      <!--// board_project/board/templates/board/comment_list.html //-->
      <!--// tr 문에 class 이름 추가 //-->
      <tr class="comment_row">
      <!--// 해당 td 문에 class 이름 추가 //-->
      <td colspan="3" class="comment_text">{{comment.text}}</td>
      <td>{{comment.author.username}}</td>
      <td>{{comment.created}}</td>
      <td><a href="{% url 'board:comment_update' comment.id %}" class="btn btn-outline-dark btn-sm btn_comment_update">Update</a></td>
      <td><a href="{% url 'board:comment_delete' comment.id %}" class="btn btn-outline-danger btn0sm btn_comment_delete">Delete</a></td>
      </tr>
Share