Django टेम्पलेट चर और जावास्क्रिप्ट


219

जब मैं Django टेम्प्लेट रेंडरर का उपयोग करके किसी पृष्ठ को प्रस्तुत करता हूं, तो मैं एक शब्दकोश चर में पास कर सकता हूं जिसमें विभिन्न मानों का उपयोग करके उन्हें पृष्ठ में हेरफेर किया जा सकता है {{ myVar }}

क्या जावास्क्रिप्ट में एक ही चर को एक्सेस करने का एक तरीका है (शायद DOM का उपयोग करके, मुझे नहीं पता कि Django चर को कैसे सुलभ बनाता है)? मैं पास में मौजूद चर में निहित मूल्यों के आधार पर AJAX लुकअप का उपयोग करके विवरण देखने में सक्षम होना चाहता हूं।

जवाबों:


291

{{variable}}सीधे HTML में दिया जाता है। एक स्रोत देखें; यह "चर" या ऐसा कुछ भी नहीं है। यह सिर्फ पाठ प्रस्तुत किया गया है।

ऐसा कहने के बाद, आप इस प्रकार के प्रतिस्थापन को अपने जावास्क्रिप्ट में डाल सकते हैं।

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

यह आपको "डायनामिक" जावास्क्रिप्ट देता है।


29
ध्यान दें कि इस समाधान के अनुसार , यह इंजेक्शन हमलों के लिए कमजोर है
केसबश

13
@ कैशेबश: ऐसे मौकों के लिए escapejsफिल्टर मौजूद है:escapejs('<>') -> u'\\u003C\\u003E'
टॉमस ज़ीलिस्की

24
संदर्भ के लिए इसे जोड़ने के लिए: यदि "someDjangoVariable" ऐसा JSON होता है, तो & quot; निकालने के लिए {{someDjangoVariable | safe}} का उपयोग करना सुनिश्चित करें;
मार्क

4
यह उत्तर केवल एक साधारण चर के लिए काम करता है, यह एक जटिल डेटा संरचना के लिए काम नहीं करता है। इस मामले में, डेटा संरचना को पार करने और जावास्क्रिप्ट में इसी तरह के निर्माण के लिए क्लाइंट-साइड कोड जोड़ना सबसे सरल उपाय है। यदि जटिल डेटा संरचना JSON प्रारूप में है, तो इसका समाधान करने के लिए एक और समाधान है, सर्वर-साइड कोड में Django टेम्पलेट के लिए एक क्रमबद्ध JSON पास करें और क्लाइंट-साइड कोड में जावास्क्रिप्ट ऑब्जेक्ट में JSON का डीसर्विलाइज़ करें। नीचे एक उत्तर इस विकल्प का उल्लेख करता है।
एलन इवेंजेलिस्टा

14
क्या होगा अगर जावास्क्रिप्ट एक अलग फ़ाइल में लिखा गया है?
the_unknown_spirit

64

चेतावनी चेक टिकट # 17419 Django कोर में इसी तरह के टैग को जोड़ने और उपयोगकर्ता द्वारा उत्पन्न डेटा के साथ इस टेम्पलेट टैग का उपयोग करके संभावित XSS भेद्यता पर चर्चा के लिए। अमाकनील की टिप्पणी टिकट में उठाए गए अधिकांश चिंताओं पर चर्चा करती है।


मुझे लगता है कि ऐसा करने का सबसे लचीला और आसान तरीका यह है कि आप जेएस कोड में जिन वेरिएबल का उपयोग करना चाहते हैं, उनके लिए एक टेम्प्लेट फिल्टर को परिभाषित करें। यह आपको यह सुनिश्चित करने की अनुमति देता है, कि आपका डेटा ठीक से बच गया है और आप इसका उपयोग जटिल डेटा संरचनाओं जैसे कि 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 टेम्प्लेट इनपुट चर की प्रतिलिपि बनाने की अनुमति देता है, यह जानने की आवश्यकता नहीं है कि जावास्क्रिप्ट द्वारा कौन सी डेटा संरचनाओं का उपयोग किया जाना चाहिए और इसलिए Django टेम्पलेट को रेंडर करने से पहले JSON में परिवर्तित कर दिया गया है। या तो इस का उपयोग करें या हमेशा जावास्क्रिप्ट के लिए सभी Django चर की प्रतिलिपि बनाएँ।
एलन इवेंजेलिस्टा


1
@ जोर्जऑर्पिनल नहीं, यह समान नहीं है। safeकेवल उचित रूपान्तरण और भागने के बिना, मान सुरक्षित है।
यारोस्लाव एडमिन

2
फिर आप django टेम्पलेट में चर कैसे प्रदर्शित करते हैं?
kbdev

1
@ सांडी वापस जब मैंने पोस्ट की तो अलग जेएस फाइल में एक विजेट होना आम था और इसे पेज सोर्स कोड में इनिशियलाइज़ किया। तो मान लीजिए कि आप function myWidget(config) { /* implementation */ }जेएस फाइल में घोषणा करते हैं और आप इसका उपयोग करते हुए कुछ पृष्ठों पर करते हैं myWidget({{ pythonConfig | js }})। लेकिन आप इसे जेएस फाइलों में उपयोग नहीं कर सकते हैं (जैसा कि आपने देखा), इसलिए इसकी सीमाएं हैं।
यारोस्लाव व्यवस्थापक

51

मेरे लिए काम करने वाला एक समाधान टेम्पलेट में छिपे इनपुट क्षेत्र का उपयोग कर रहा है

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

फिर इस तरह से जावास्क्रिप्ट में मूल्य प्राप्त करना,

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

3
हालांकि सावधान रहना। आप चर / रूप का उपयोग कैसे करते हैं, इस पर निर्भर करते हुए, उपयोगकर्ता जो कुछ भी चाहते हैं, उसमें डाल सकता है।
एंडीएल

3
आप अपने इनपुट क्षेत्र को आसानी से सेट करना चाहते हैं (इस लिंक को देखें w3schools.com/tags/att_input_readonly.asp )
nu everest

यदि यह ऐसा कुछ है जो डेटाबेस में परिवर्तन नहीं करेगा या डेटाबेस क्वेरी को नहीं भेजा जाएगा तो यह ठीक होगा। @ एंडीएल
जेम्स ११

3
दोस्तों ... उपयोगकर्ता जो चाहे कर सकते हैं। ब्राउज़र आजकल पूरी तरह से चित्रित डोम निरीक्षक और डीबगिंग टूल के साथ इतना आसान बनाते हैं। कहानी का नैतिक: आप सभी सर्वर पर डेटा सत्यापन करते हैं
user2867288

1
कृपया कोई मुझे बताए कि आप उस चर को बाहरी जावास्क्रिप्ट फ़ाइल में कैसे एक्सेस करेंगे?
अहिष्टम् दिसम्

27

Django 2.1 के रूप में, विशेष रूप से इस उपयोग के मामले के लिए खाका बनाया गया है json_script

https://docs.djangoproject.com/en/3.0/ref/templates/builtins/#json-script

नया टैग सुरक्षित रूप से टेम्पलेट मानों को क्रमबद्ध करेगा और XSS से बचाता है।

Django डॉक्स अंश:

जावास्क्रिप्ट के साथ उपयोग के लिए तैयार, टैग में लिपटे JSON के रूप में सुरक्षित रूप से पायथन ऑब्जेक्ट को आउटपुट करता है।


10

यहाँ वह है जो मैं बहुत आसानी से कर रहा हूँ: मैंने अपने खाके के लिए अपनी बेस। Html फ़ाइल को संशोधित किया और उसे नीचे रखा:

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

तब जब मैं जावास्क्रिप्ट फ़ाइलों में एक चर का उपयोग करना चाहता हूं, मैं एक डीजेडेटा शब्दकोश बनाता हूं और मैं इसे एक json द्वारा संदर्भ में जोड़ता हूं: context['DJdata'] = json.dumps(DJdata)

आशा करता हूँ की ये काम करेगा!


इसका उपयोग न करें, यह स्क्रिप्ट इंजेक्शन (XSS) के लिए असुरक्षित है।
पीसीवर्ल्ड

8

एक शब्दकोश के लिए, आप पहले JSON के लिए एन्कोडिंग के सर्वश्रेष्ठ हैं। आप simplejson.dps () का उपयोग कर सकते हैं या यदि आप ऐप इंजन में डेटा मॉडल से कनवर्ट करना चाहते हैं, तो आप GQLEncoder लाइब्रेरी से एनकोड () का उपयोग कर सकते हैं।


1
ध्यान दें कि 'सिम्पलसन' django 1.7 के रूप में 'json' बन गया है, मुझे विश्वास है।
पांच

4

मैं सिमिलर मुद्दे का सामना कर रहा था और एस.लॉट द्वारा सुझाए गए जवाब ने मेरे लिए काम किया।

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

हालांकि मैं यहां प्रमुख कार्यान्वयन सीमा को इंगित करना चाहूंगा । यदि आप अपने जावास्क्रिप्ट कोड को अलग फ़ाइल में डालने की योजना बना रहे हैं और उस फ़ाइल को अपने टेम्पलेट में शामिल करें। यह काम नहीं करेगा।

यह तभी काम करता है जब आप मुख्य टेम्पलेट और जावास्क्रिप्ट कोड एक ही फाइल में होते हैं। संभवतः django की टीम इस सीमा को संबोधित कर सकती है।


1
हम इसे कैसे दूर कर सकते हैं?
सेबा तोथ

2
इसे दूर करने के लिए, आप वैश्विक जावास्क्रिप्ट वैरिएबल को उस जगह रख सकते हैं, जैसे कि स्टैटिक जावास्क्रिप्ट फाइल को शामिल करने से ठीक पहले दिखाया गया उदाहरण। आपकी स्थिर जावास्क्रिप्ट फ़ाइल का इस तरह से सभी वैश्विक चर तक पहुंच होगी।
बोबोर्ट

इसका उपयोग न करें, यह स्क्रिप्ट इंजेक्शन (XSS) के लिए असुरक्षित है।
पीसीवर्ल्ड

वे सर्वर साइड पर डेटा मान्य कर सकते हैं।
मुहम्मद फैजान फरीद

4

मैं इससे भी जूझ रहा हूं। सतह पर ऐसा लगता है कि उपरोक्त समाधान काम करना चाहिए। हालाँकि, django आर्किटेक्चर के लिए आवश्यक है कि प्रत्येक HTML फ़ाइल के अपने स्वयं के रेंडर किए गए वैरिएबल हैं (जो कि {{contact}}रेंडर किए जाते हैं contact.html, जबकि {{posts}}उदाहरण के लिए index.htmlऔर इसी तरह)। दूसरी ओर, <script>टैग के बाद दिखाई {%endblock%}में base.htmlजहाँ से contact.htmlऔर index.htmlप्राप्त करती हैं। मूल रूप से इसका मतलब है कि किसी भी समाधान सहित

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

विफल होने के लिए बाध्य है, क्योंकि चर और स्क्रिप्ट एक ही फ़ाइल में सह-अस्तित्व में नहीं हो सकते।

सरल समाधान जो अंततः मेरे साथ आया था, और मेरे लिए काम करता था, बस चर को आईडी के साथ टैग के साथ लपेटना था और बाद में इसे जेएस फ़ाइल में संदर्भित करना चाहिए, जैसे:

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

और फिर:

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

और बस में शामिल हैं <script src="static/js/somecode.js"></script>में base.htmlहमेशा की तरह। बेशक यह केवल सामग्री प्राप्त करने के बारे में है। सुरक्षा के संबंध में, बस अन्य उत्तरों का पालन करें।


आप शायद .textContentइसके बजाय उपयोग करना चाहते हैं .innerHTML, क्योंकि अन्यथा HTML- एन्कोडेड प्राप्त करने वाली इकाइयाँ जेएस चर का भी हिस्सा होंगी। लेकिन फिर भी यह 1: 1 को पुन: पेश नहीं किया जा सकता है (मुझे यकीन नहीं है)।
pcworld

एक स्पष्टीकरण । मैं वैरिएबल में फ़ील्ड मानों को कैप्चर करने के लिए इसी तरह का उपयोग करता हूं (आईडी के रूप में गतिशील रूप से बनाई गई) का उपयोग कर रहा है, और यह काम कर रहा है (लेकिन केवल एक फॉर्मसेट पंक्ति के लिए )। मैं जो कुछ भी पाने में सक्षम नहीं हूं, वह फॉर्मसेट फ़ील्ड्स की सभी पंक्तियों से मूल्यों को पकड़ने के लिए है , जो मैन्युअल रूप से पॉपुलेट किए जा रहे हैं (यानी लूप का उपयोग करके एक html तालिका में )। जैसा कि आप कल्पना करेंगे कि केवल अंतिम फॉर्मसेट पंक्ति के चर को चर में पारित किया गया है, और इससे पहले के मान बाद वाले मानों के साथ ओवरराइट किए गए हैं, क्योंकि लूप फॉर्मेट पंक्तियों के माध्यम से आगे बढ़ता है। क्या इसके आसपास कोई रास्ता है?
user12379095

3

पाठ के रूप में एक Django फ़ील्ड में संग्रहीत एक जावास्क्रिप्ट ऑब्जेक्ट के लिए, जिसे फिर से एक जावास्क्रिप्ट ऑब्जेक्ट बनने की आवश्यकता है गतिशील रूप से ऑन-पेज स्क्रिप्ट में डाला जाता है, आपको दोनों का उपयोग करने की आवश्यकता है 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

विश्व स्तर पर एक चर घोषित करने का हिस्सा वास्तव में मददगार था।
राहुल

यदि आप ऊपर जैसे टेम्प्लेट से js वेरिएबल्स में डेटा रेंडर करते हैं तो एक ही पेज (उन्हें वैश्विक बनाने) में रेंडर करना होगा और अन्य कोड अलग js फ़ाइल में जाता है। सर्वर साइड में डेटा मान्य होना चाहिए क्योंकि उपयोगकर्ता ब्राउज़र से बदल सकता है।
मुहम्मद फैजान फरीद

1

मैं Django 2.1 में इस तरह का उपयोग करता हूं और मेरे लिए काम करता हूं और यह तरीका सुरक्षित है (संदर्भ) :

Django पक्ष:

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 (स्क्रिप्ट इंजेक्शन) संभव है।
पीसीवर्ल्ड

0

जावास्क्रिप्ट के अंदर मेरे लिए काम करने वाली दो चीजें हैं:

'{{context_variable|escapejs }}'

और अन्य: view.py में

from json import dumps as jdumps

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

और HTML में:

{{ message|safe }}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.