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


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 코드에서 사용하려는 변수에 대한 템플릿 필터를 정의하는 것입니다. 이 데이터가 제대로 이스케이프와 같은 복잡한 데이터 구조로 사용할 수 있습니다, 당신을 보장 할 수 dict와 list. 그래서 많은 찬성에 대한 답변이 있지만이 답변을 작성합니다.

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

// 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.html와 index.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

다시 자바 스크립트 객체가 동적에 페이지 스크립트에 삽입 될 필요가 텍스트와 같은 장고 필드에 저장된 자바 스크립트 객체를 들어, 당신은 모두 사용해야 escapejs과 JSON.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.