AJAX

What is AJAX?

  • Asynchronous JavaScript And Xml

    • ๋น„๋™๊ธฐ ์š”์ฒญ์„ ๋ณด๋‚ธ๋‹ค

AJAX ์š”์ฒญ

: XHR์„ ๋ณด๋‚ธ๋‹ค

XMLHttpREquest (XHR)

  • Use XMLHttpRequest (XHR) objects to interact with servers.

  • You can retrieve data from a URL without having to do a full page refresh.

  • This enables a Web page to update just part of a page without disrupting what the user is doing.

  • XMLHttpRequest is used heavily in AJAX programming.

Django API: Ping-Pong ๋งŒ๋“ค๊ธฐ

๊ฐ€์ƒ ํ™˜๊ฒฝ ๋งŒ๋“ค๊ธฐ

python -m venv venv

ํ•ด๋‹น ํ”„๋กœ์ ํŠธ์—์„œ pip list ์ฐพ๊ฒŒ ํ•˜๊ธฐ

source venv/bin/activate

๊ฐ€์ƒ ํ™˜๊ฒฝ ์•ˆ์— pip ์„ค์น˜

(venv) 
chloe@chloe-XPS-15-9570 ~/Workspace/VanillaJS/live/AJAX
$ pip -m pip install --upgrade pip

๊ฐ€์ƒ ํ™˜๊ฒฝ ์•ˆ์— django ์„ค์น˜

(venv) 
chloe@chloe-XPS-15-9570 ~/Workspace/VanillaJS/live/AJAX
$ pip install django==2.1.15

art package ์‚ฌ์šฉํ•˜๊ธฐ

installation

pip install art

ping.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>์•„-ํŠธ</title>
</head>
<body>
    <label for="userInput">Input: </label>
    <input id="userInput" name="inputText" type="text">
    <pre id="resultArea">

    </pre>
    <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
    <script>
        // 1. input#userInput ์˜ 'change' ์ด๋ฒคํŠธ ๋•Œ, value๊ฐ’์„ '/art/pong' ์œผ๋กœ ๋ณด๋‚ธ๋‹ค
        const userInput = document.querySelector('#userInput')
        userInput.addEventListener('input', function(event){
            // input type="text"๋Š” focus out === enter
            const inputText = userInput.value
            // 2. pong์ด ๋ฐ›์•„์„œ ๋‹ค์‹œ JSON์œผ๋กœ ์‘๋‹ต์„ ๋ณด๋‚ธ๋‹ค
            axios.get('/arts/pong/', {
                params: {
                    inputText: inputText,
                }
            })
                .then(function(res){ 
                 // 3. ์‘๋‹ต JSON์˜ ๋‚ด์šฉ์„ div#resultArea์— ํ‘œ์‹œํ•œ๋‹ค
                    const resultArea = document.querySelector('#resultArea')
                    resultArea.innerText = res.data.content
        })
    })
    </script>
    
</body>
</html>

views.py

from django.shortcuts import render
from django.http import JsonResponse

import art 

# Create your views here.
def ping(request):
    return render(request, 'arts/ping.html')

def pong(request):
    user_input = request.GET.get('inputText')
    art_text = art.text2art(user_input)
    data = {
        'success': True,
        'content': art_text,
    }
    return JsonResponse(data)

์ข‹์•„์š” AJAX๋กœ ๊ตฌํ˜„ํ•˜๊ธฐ

  1. AJAX (browser๊ฐ€ ๋ณด๋‚ด๋Š” HTTP Request)๋ฅผ ํ†ตํ•ด data ์กฐ์ž‘ URL์— ์š”์ฒญ (Django app) ์„ ๋ณด๋‚ด์„œ

  2. ๋ฐ›์€ ์‘๋‹ต์˜ data๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ, ํ•˜ํŠธ๋งŒ HTML ์†์„ฑ ๋ณ€๊ฒฝ

index.html


<div data-gb-custom-block data-tag="extends" data-0='base.html'></div>

<div data-gb-custom-block data-tag="block">

  <h2>INDEX</h2>
  

<div data-gb-custom-block data-tag="for">

    <h3>์ž‘์„ฑ์ž: {{ article.user }}</h3>
    <h4>์ œ๋ชฉ: {{ article.title }}</h4>
    <p>๋‚ด์šฉ: {{ article.content }}</p>
    <span>AJAX ๋ฐฉ์‹</span>

      

<div data-gb-custom-block data-tag="if">

        <i class="fas fa-heart fa-lg likeButtons" style="color:crimson" data-id="{{article.pk}}"></i>
      

<div data-gb-custom-block data-tag="else"></div>

      <i class="fas fa-heart fa-lg likeButtons" style="color:black" data-id="{{article.pk}}"></i>
      

</div>

      
    <span>๊ธฐ์กด ๋ฐฉ์‹</span>
    <a href="

<div data-gb-custom-block data-tag="url" data-0='articles:like'></div>">
      <div data-gb-custom-block data-tag="if">

        <i class="fas fa-heart fa-lg" style="color:crimson"></i>
      

<div data-gb-custom-block data-tag="else"></div>

        <i class="fas fa-heart fa-lg" style="color:black"></i>
      

</div>

    </a>
    <span id="likeCount-{{article.pk}}">{{article.like_users.all|length}}</span> ๋ช…์ด ์ด ๊ธ€์„ ์ข‹์•„ํ•ฉ๋‹ˆ๋‹ค.
    <hr>
  

</div>

  <a href="

<div data-gb-custom-block data-tag="url" data-0='articles:create'></div>">CREATE</a>

    <script>
      const likeButtonList = document.querySelectorAll('.likeButtons')
      likeButtonList.forEach(likeButton => {
        likeButton.addEventListener('click', e => {
        // 1. axios๋กœ ์š”์ฒญ๋ณด๋‚ด๊ธฐ(like)
        //const articleID = e.target.getAttribute('data-id')
        const articleID = e.target.dataset.id
                          // -> data- ๋กœ ์‹œ์ž‘ํ•˜๋Š” attribute๋Š” dataset์— ์ €์žฅ๋˜๊ณ , dash ๋’ค์˜ id๋กœ ๋ฐ๋ ค์˜ฌ ์ˆ˜ ์žˆ์Œ
        
        <div data-gb-custom-block data-tag="if">

          axios.get(`/articles/${articleID}/like_api/`)
            .then( res => {
              // ๊ฒฐ๊ณผ ๋ฐ›์€ ๋’ค์— ํ•  ๊ฒƒ๋“ค
              
              likeCount = document.querySelector(`#likeCount-${articleID}`).innerText = res.data.count

              // ํ˜„์žฌ db์— ์ €์žฅ๋œ ๊ฐ’์ด liked=True ๋ผ๋ฉด,
              if (res.data.liked){
                e.target.style.color = 'crimson'
              }else{
                e.target.style.color = 'black'
              }
            })
        

<div data-gb-custom-block data-tag="else"></div>

            alert('๋น„ ๋กœ๊ทธ์ธ ์‚ฌ์šฉ์ž๋Š” ์ข‹์•„์š”๋ฃฐ ๋ˆ„๋ฅผ ์ˆ˜ ์—†์–ด์š” ใ… _ใ… ')
        

</div>

      })
    })
    </script>

</div>

views.py

@login_required
def like_api(request, article_pk):
    user = request.user 
    article = get_object_or_404(Article, pk=article_pk)
    
    if article.like_users.filter(pk=user.pk).exists():
        article.like_users.remove(user)
        liked = False
    else:
        article.like_users.add(user)
        liked = True

    context = {
        'liked': liked,
        'count': article.like_users.count()
    }

    return JsonResponse(context)  

Last updated