장고 템플릿 변수와 자바 스크립트


219

Django 템플릿 렌더러를 사용하여 페이지를 렌더링 할 때 다양한 값을 포함하는 사전 변수를 전달하여을 사용하여 페이지에서 해당 값을 조작 할 수 있습니다 {{ myVar }}.

Javascript에서 동일한 변수에 액세스하는 방법이 있습니까 (아마 DOM을 사용하면 Django가 변수에 액세스하는 방법을 모르겠습니다)? 전달 된 변수에 포함 된 값을 기반으로 AJAX 조회를 사용하여 세부 정보를 조회 할 수 있기를 원합니다.

답변:


291

{{variable}}HTML로 직접 대체됩니다. 뷰 소스를 수행하십시오. "가변"또는 이와 유사한 것이 아닙니다. 방금 렌더링 된 텍스트입니다.

그렇게 말하면, 이런 종류의 대체물을 JavaScript에 넣을 수 있습니다.

<script type="text/javascript"> 
   var a = "{{someDjangoVariable}}";
</script>

이것은 "동적"자바 스크립트를 제공합니다.


29
이 솔루션 에 따르면 이것은 주입 공격에 취약합니다.
Casebash

13
@Casebash : 그러한 경우에 escapejs필터가 존재합니다 :escapejs('<>') -> u'\\u003C\\u003E'
Tomasz Zieliński

24
"someDjangoVariable"이 JSON 인 경우 {{someDjangoVariable | safe}}를 사용하여 & quot;
Mark

4
이 답변은 간단한 변수에만 작동하며 복잡한 데이터 구조에는 작동하지 않습니다. 이 경우 가장 간단한 해결책은 클라이언트 측 코드를 추가하여 데이터 구조를 순회하고 Javascript에서 유사한 구조를 작성하는 것입니다. 복잡한 데이터 구조가 JSON 형식 인 경우 다른 솔루션은 직렬화하고 직렬화 된 JSON을 서버 측 코드의 Django 템플릿에 전달하고 클라이언트 측 코드의 자바 스크립트 객체에서 JSON을 역 직렬화하는 것입니다. 아래의 답변 중 하나가이 대안을 언급합니다.
Alan Evangelista

14
자바 스크립트가 다른 파일로 작성되면 어떻게 되나요?
the_unknown_spirit

64

주의 Django 코어에 유사한 태그를 추가하고이 템플릿 태그를 사용자 생성 데이터와 함께 사용하여 발생할 수있는 XSS 취약성에 대해 논의 하려면 티켓 # 17419 를 확인하십시오 . amacneil의 의견 은 티켓에서 제기 된 대부분의 문제를 설명합니다.


가장 유연하고 편리한 방법은 JS 코드에서 사용하려는 변수에 대한 템플릿 필터를 정의하는 것입니다. 이 데이터가 제대로 이스케이프와 같은 복잡한 데이터 구조로 사용할 수 있습니다, 당신을 보장 할 수 dictlist. 그래서 많은 찬성에 대한 답변이 있지만이 답변을 작성합니다.

템플릿 필터의 예는 다음과 같습니다.

// myapp/templatetags/js.py

from django.utils.safestring import mark_safe
from django.template import Library

import json


register = Library()


@register.filter(is_safe=True)
def js(obj):
    return mark_safe(json.dumps(obj))

이 템플릿 필터는 변수를 JSON 문자열로 변환합니다. 다음과 같이 사용할 수 있습니다.

// myapp/templates/example.html

{% load js %}

<script type="text/javascript">
    var someVar = {{ some_var | js }};
</script>

3
Django 템플릿 입력 변수를 Javascript로 복사 할 수 있기 때문에 서버 측 코드는 Javascript가 사용해야하는 데이터 구조를 알 필요가 없으므로 Django 템플릿을 렌더링하기 전에 JSON으로 변환해야하기 때문에 좋습니다. 이것을 사용하거나 항상 모든 Django 변수를 Javascript로 복사하십시오.
Alan Evangelista


1
@JorgeOrpinel 아니요, 동일하지 않습니다. safe적절한 전환 및 이탈없이 가치 만 안전한 것으로 표시합니다.
Yaroslav 관리자

2
그런 다음 django 템플릿에 변수를 어떻게 표시합니까?
kbdev 2016 년

1
@Sandi은 게시 할 때 별도의 JS 파일에 위젯을 가지고 페이지 소스 코드에서 초기화하는 것이 일반적이었습니다. function myWidget(config) { /* implementation */ }JS 파일로 선언 하고을 사용하여 일부 페이지에서 사용 한다고 가정 해 봅시다 myWidget({{ pythonConfig | js }}). 그러나 JS 파일에서는 사용할 수 없으므로 (알다시피) 한계가 있습니다.
Yaroslav 관리자

51

나를 위해 일한 해결책은 템플릿에서 숨겨진 입력 필드를 사용하는 것입니다.

<input type="hidden" id="myVar" name="variable" value="{{ variable }}">

그런 다음 자바 스크립트로 값을 가져옵니다.

var myVar = document.getElementById("myVar").value;

3
그래도 조심하십시오. 변수 / 양식을 사용하는 방법에 따라 사용자는 원하는대로 넣을 수 있습니다.
AndyL

3
입력 필드를 읽기 전용으로 설정할 수도 있습니다 (이 링크 w3schools.com/tags/att_input_readonly.asp 참조 )
nu everest

데이터베이스를 변경하지 않거나 데이터베이스 쿼리로 전송되지 않는 것이면 좋을 것입니다. @AndyL
James111

3
얘들 아 ... 사용자는 어쨌든 원하는 것을 할 수 있습니다. 브라우저는 오늘날 모든 기능을 갖춘 DOM 검사기 및 디버깅 도구를 사용하여 쉽게 만들 수 있습니다. 이야기의 교훈 : 서버 에서 데이터 유효성 검사를 모두 수행하십시오 .
user2867288

1
외부 JavaScript 파일에서 해당 변수에 어떻게 액세스 할 수 있습니까?
Ahtisham


10

내가하는 일이 매우 쉽습니다. 템플릿의 base.html 파일을 수정하고 맨 아래에 배치했습니다.

{% if DJdata %}
    <script type="text/javascript">
        (function () {window.DJdata = {{DJdata|safe}};})();
    </script>
{% endif %}

그런 다음 자바 스크립트 파일에서 변수를 사용하려면 DJdata 사전을 만들고 json으로 컨텍스트에 추가합니다. context['DJdata'] = json.dumps(DJdata)

그것이 도움이되기를 바랍니다!


이것을 사용하지 마십시오. 스크립트 삽입 (XSS)에 취약합니다.
pcworld

8

사전의 경우 먼저 JSON으로 인코딩하는 것이 가장 좋습니다. simplejson.dumps ()를 사용하거나 App Engine의 데이터 모델에서 변환하려는 경우 GQLEncoder 라이브러리에서 encode ()를 사용할 수 있습니다.


1
django 1.7에서 'simplejson'이 'json'이되었습니다.
fiveclubs

4

S.Lott가 제안한 비슷한 문제와 대답에 직면했습니다.

<script type="text/javascript"> 
   var a = "{{someDjangoVariable}}"
</script>

그러나 여기서 중요한 구현 제한 사항 을 지적하고 싶습니다 . 자바 스크립트 코드를 다른 파일에 넣고 해당 파일을 템플릿에 포함시키려는 경우. 작동하지 않습니다.

메인 템플릿과 자바 스크립트 코드가 동일한 파일에있는 경우에만 작동합니다. 아마도 django 팀 이이 한계를 해결할 수 있습니다.


1
우리는 이것을 어떻게 극복 할 수 있습니까?
Csaba Toth

2
이를 극복하기 위해 정적 Javascript 파일을 포함하기 직전에 표시된 예제와 같은 전역 Javascript 변수를 배치 할 수 있습니다. 정적 Javascript 파일은 모든 전역 변수에 액세스 할 수 있습니다.
Bobort

이것을 사용하지 마십시오. 스크립트 삽입 (XSS)에 취약합니다.
pcworld

서버 측에서 유효한 데이터를 사용할 수 있습니다.
Muhammad Faizan이

4

나도 이것으로 고투하고있다. 표면적으로는 위의 솔루션이 작동하는 것 같습니다. 그러나 장고 아키텍처는 각 html 파일에 고유 한 렌더링 된 변수가 있어야합니다 (즉, {{contact}}에 렌더링되는 contact.html동안 {{posts}}예를 들어 index.html등등). 반면에, <script>태그는 뒤에 표시 {%endblock%}에서 base.html어떤에서 contact.htmlindex.html상속. 이것은 기본적으로

<script type="text/javascript">
    var myVar = "{{ myVar }}"
</script>

변수와 스크립트가 같은 파일에 공존 할 수 없으므로 실패로 바인드됩니다.

내가 결국 생각해 낸 간단한 해결책은 변수를 id로 태그로 감싸고 나중에 js 파일에서 다음과 같이 참조하는 것입니다.

// index.html
<div id="myvar">{{ myVar }}</div>

그리고:

// somecode.js
var someVar = document.getElementById("myvar").innerHTML;

단지 포함 <script src="static/js/somecode.js"></script>base.html평소와 같이. 물론 이것은 내용을 얻는 것입니다. 보안과 관련하여 다른 답변을 따르십시오.


HTML 인코딩 된 엔티티는 JS 변수의 일부이기 때문에, .textContent대신에 사용하고 싶을 것입니다 .innerHTML. 그러나 그때조차도 1 : 1로 재현되지 않을 수도 있습니다 (확실하지 않습니다).
pcworld

설명 . 비슷한 방식으로 변수에서 필드 값을 캡처하고 (양식에서 동적으로 생성 된 ID 사용) 작동합니다 (단 하나의 formset row 만 해당 ). 내가 해결할 수없는 것은 formset 필드의 모든 행에서 값을 캡처 하는 것입니다.이 필드 는 수동으로 채워집니다 (예 : for loop 사용하는 html 테이블 ). 마지막 formset 행의 변수 만 시각화하면 변수에 전달되고 for 루프가 formset 행을 통해 진행될 때 그 이전 값이 후자의 값으로 겹쳐 씁니다. 이것에 대한 방법이 있습니까?
user12379095

3

다시 자바 스크립트 객체가 동적에 페이지 스크립트에 삽입 될 필요가 텍스트와 같은 장고 필드에 저장된 자바 스크립트 객체를 들어, 당신은 모두 사용해야 escapejsJSON.parse():

var CropOpts = JSON.parse("{{ profile.last_crop_coords|escapejs }}");

Django escapejs는 따옴표를 올바르게 처리하고 JSON.parse()문자열을 JS 객체로 다시 변환합니다.


2

변수를 외부 .js 스크립트로 전달하려면 전역 변수를 선언하는 다른 스크립트 태그를 스크립트 태그 앞에 추가해야합니다.

<script type="text/javascript">
    var myVar = "{{ myVar }}"
</script>

<script type="text/javascript" src="{% static "scripts/my_script.js" %}"></script>

data 보기에서 평소와 같이 정의됩니다. get_context_data

def get_context_data(self, *args, **kwargs):
    context['myVar'] = True
    return context

전역 적으로 변수를 선언하는 부분이 실제로 도움이되었습니다.
Rahul

위와 같은 템플릿에서 데이터를 js 변수로 렌더링하면 동일한 페이지로 렌더링해야하며 (전역 적으로 작성) 다른 코드는 별도의 js 파일로 이동합니다. 사용자는 브라우저에서 변경할 수 있으므로 서버 측에서 유효한 데이터가 있어야합니다.
Muhammad Faizan이

1

나는 장고 2.1 에서이 방법을 사용하고 나를 위해 일하며이 방법은 안전합니다 (참조) :

장고 쪽 :

def age(request):
    mydata = {'age':12}
    return render(request, 'test.html', context={"mydata_json": json.dumps(mydata)})

HTML 쪽 :

<script type='text/javascript'>
     const  mydata = {{ mydata_json|safe }};
console.log(mydata)
 </script>

0

다음과 같이 배열 변수가 문자열로 선언 된 전체 스크립트를 어셈블 할 수 있습니다.

views.py

    aaa = [41, 56, 25, 48, 72, 34, 12]
    prueba = "<script>var data2 =["
    for a in aaa:
        aa = str(a)
        prueba = prueba + "'" + aa + "',"
    prueba = prueba + "];</script>"

다음과 같이 문자열을 생성합니다

prueba = "<script>var data2 =['41','56','25','48','72','34','12'];</script>"

이 문자열이 있으면 템플릿으로 보내야합니다.

views.py

return render(request, 'example.html', {"prueba": prueba})

예를 들어 템플릿에서 필요한 자바 스크립트 코드 바로 앞의 htm 코드로 문학적 방식으로이를 받아 해석합니다.

주형

{{ prueba|safe  }}

그 아래 코드는 나머지 코드이므로 예제에서 사용할 변수는 data2입니다.

<script>
 console.log(data2);
</script>

그렇게하면 데이터 유형을 유지할 수 있습니다.


aaa숫자 만 포함 할 것이 확실한 경우에만 사용하십시오 . 그렇지 않으면 XSS (스크립트 삽입)가 가능합니다.
pcworld

0

Javascript 내에서 나를 위해 일한 두 가지가 있습니다.

'{{context_variable|escapejs }}'

및 기타 : views.py

from json import dumps as jdumps

def func(request):
    context={'message': jdumps('hello there')}
    return render(request,'index.html',context)

그리고 html에서 :

{{ message|safe }}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.