본문 바로가기

Python/Django

Django Template, render_to_string # backend에서 data 받기 #render_to_string #loader

728x90
반응형

Ajax를 통해서 HTTP통신을 하는 경우

backend에 request를 보내고 거기에 대한 frontend에서 response를 받고, reponse 안에 data를 담아올 수 있습니다.

받아온 data를 화면 전환 없이 특정 html 부분만 바꿀때 Ajax를 많이 활용합니다.

 

경우에 따라서는 화면 전체를 다른 페이지로 전환을 하면서, data를 backend에서 받아오고 싶을 수 있습니다.

 

Django template의 경우 context에 담아서 render해 줄 경우 html에 바로 뿌려줄 수 있지만, 데이터를 받아서 데이터 자체를 활용하기가 수월하지 않습니다.

 

즉, 원하는 것은 다음과 같은 상황입니다.

1) 페이지 전환을 특정 html로 완전히 바꿔주고

2) context도 활용하면서

3) ajax를 통해 backend로부터 받은 data도 활용

 

위와 같은 상황에서 이용가능한 한가지 방법인 Django template의 render_to_string 을 활용해보겠습니다.

from django.template import loader

 

위와 같이 import 한 loader 모듈을 들어가 봅니다.

def render_to_string(template_name, context=None, request=None, using=None):
    """
    Load a template and render it with a context. Return a string.

    template_name may be a string or a list of strings.
    """
    if isinstance(template_name, (list, tuple)):
        template = select_template(template_name, using=using)
    else:
        template = get_template(template_name, using=using)
    return template.render(context, request)

loader.py에는 select_template, get_template, render_to_string, _engine_list 의 함수들이 존재합니다.

render_to_string의 설명을 보면 context와 함께 template을 render 한다고 되어있습니다.

일반적으로 사용하는 render, context와 같은 기능을 할 수 있는데 그 값을 string으로 return 하는 것입니다.

 

Backend에서 string으로 return 을 하고,

Frontend에서는 Ajax를 통해서 [context와 함께 render한 html 페이지를], string으로 받을 수 있게 됩니다.

 

views를 url과 연결해서 직접 확인해보겠습니다.

 

views.py

def home(request):
    return render(request, 'home.html')


def ajax_data_view(request):
    context = {
        'title': '타이틀',
        'zero': 0,
        'one': 1,
    }
    contents = loader.render_to_string('ajax_test.html', context, request)
    return JsonResponse({'contents': contents,'status':200})

 

urls.py

from django.urls import path
from . import views

urlpatterns = [
    path('', views.home),
    path('ajax-test', views.ajax_data_view),
]

 

ajax_test.html

<!DOCTYPE html>
<html lang="en">
<head>
    <title>{{ title }}</title>
</head>
<body>
    <h1 style="background-color: red;">{{ zero }}</h1>
    <h2 style="background-color: yellow;">{{ one }}</h2>
    <h3> {{request.user}} </h3>
</body>
</html>

 

이제 http://127.0.0.1:8000/ajax-test 로 이동해서 확인

해당 url로 직접 오면 json에 string 형태로 담겨온 것을 확인 가능합니다.

"contents"에 담긴 값을 보면 ajax_test.html이 담겨왔는데 <title>, <h1>, <h2>, <h3> 태그에 담긴 값들이 context에 맞게 변해 있는 것을 확인이 가능합니다.

이제 위 "contents"의 내용을 javascript를 통해 body 태그에 넣어주면 됩니다.

 

home.tml (url: /)

{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
    <script src="{% static 'js/AjaxRender.js' %}"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.3/jquery.min.js" integrity="sha512-STof4xm1wgkfm7heWqFJVn58Hm3EtS31XFaagaa8VMReCXAkQnJZ+jEy8PCC/iT18dFy95WcExNHFTqLyp72eQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
    <title>Home</title>
</head>
<body>
  <h1>Home</h1>
    <button onclick="ajaxRender()">ajax-render</button>
</body>
</html>

 

button에 달아준 onclick 함수는 다음과 같습니다.

function ajaxRender(){
    const body = document.querySelector("body")
    $.ajax({
        url: '/ajax-test',
        method: 'GET',
        success: function (data) {
            body.innerHTML = data.contents;
            console.log(data.status);
        }
    });
}

ajax-render 버튼을 눌러서 아래를 확인해봅시다

1) ajax_test.html이 제대로 잘 입혀지는지   (페이지 전환을 특정 html로 바꿔주고)

2) context로 넘겨준 값들이 잘 불러와지     (context도 활용하면서)

3) 200이 콘솔창에 찍히는지                       (ajax를 통해 backend로부터 받은 data도 활용)

 

1) ajax_test.html이 입혀졌고,  2) context로 넘겨준 값들이 잘 불러와졌고, 3) 200이 콘솔창에도 찍혔습니다.

그럴까요? 그렇지 않으니 물어보겠죠?

 

<head> 태그 내에 적용한 값들은 적용이 되지 않았습니다. 이를 Elements를 보고 확인해보겠습니다.

<head> 태그에 있는 부분은 home.html의 부분을 그대로 유지하고 있고

<body> 태그에 있는 부분만 반영된 것을 확인할 수 있습니다.

javascript를 작성한 부분을 보면 body tag를 변수로 잡고 innerHTML을 변경했기 때문입니다.

 

그럼 이번엔 html tag를 잡고 innerHTML을 변경해보겠습니다.

function ajaxRender(){
    const html = document.querySelector("html")
    $.ajax({
        url: '/ajax-test',
        method: 'GET',
        success: function (data) {
            html.innerHTML = data.contents;
            console.log(data.status);
        }
    });
}

head부분과 그 안에 설정한 context 값들이 모두 반영되었고, 콘솔도 200이 찍혔습니다.

 

* 요약 *

1) django > template > loader.py > def render_to_string

2) django > http > response.py > class JsonResponse 

3) Ajax

728x90
반응형