Kiedy renderuję stronę przy użyciu renderera szablonów Django, mogę przekazać zmienną słownikową zawierającą różne wartości, aby manipulować nimi na stronie przy użyciu {{ myVar }}
.
Czy istnieje sposób na dostęp do tej samej zmiennej w Javascript (być może przy użyciu DOM, nie wiem, jak Django udostępnia zmienne)? Chcę mieć możliwość wyszukiwania szczegółów przy użyciu wyszukiwania AJAX na podstawie wartości zawartych w przekazywanych zmiennych.
escapejs
istnieje filtr:escapejs('<>') -> u'\\u003C\\u003E'
UWAGA Sprawdź bilet nr 17419 w celu omówienia dodawania podobnego znacznika do rdzenia Django i możliwych luk w zabezpieczeniach XSS wprowadzonych przy użyciu tego znacznika szablonu z danymi generowanymi przez użytkownika. Komentarz od amacneil omawia większość obaw zgłoszonych na bilecie.
Myślę, że najbardziej elastycznym i poręcznym sposobem na to jest zdefiniowanie filtru szablonu dla zmiennych, których chcesz używać w kodzie JS. Dzięki temu masz pewność, że twoje dane są poprawnie ucieczkowe i możesz ich używać ze złożonymi strukturami danych, takimi jak
dict
ilist
. Dlatego piszę tę odpowiedź, mimo że istnieje akceptowana odpowiedź z dużą liczbą głosów pozytywnych.Oto przykład filtru szablonu:
Ten szablon filtrów konwertuje zmienną na ciąg JSON. Możesz go używać w następujący sposób:
źródło
safe
oznacza tylko wartość jako bezpieczną, bez odpowiedniej konwersji i ucieczki.function myWidget(config) { /* implementation */ }
w pliku JS i używasz go na niektórych stronach za pomocąmyWidget({{ pythonConfig | js }})
. Ale nie można go używać w plikach JS (jak zauważyłeś), więc ma swoje ograniczenia.Rozwiązaniem, które mi pomogło, jest użycie ukrytego pola wejściowego w szablonie
Następnie otrzymuję wartość w javascript w ten sposób,
źródło
Jak Django 2.1, nowy zbudowany w szablon został wprowadzony specjalnie dla tego przypadku użycia:
json_script
.https://docs.djangoproject.com/en/3.0/ref/templates/builtins/#json-script
Nowy tag bezpiecznie serializuje wartości szablonu i chroni przed XSS.
Fragment dokumentu Django:
źródło
Oto, co robię bardzo łatwo: zmodyfikowałem plik base.html dla mojego szablonu i umieściłem go na dole:
następnie, gdy chcę użyć zmiennej w plikach javascript, tworzę słownik DJdata i dodaje go do kontekstu za pomocą json:
context['DJdata'] = json.dumps(DJdata)
Mam nadzieję, że to pomoże!
źródło
W przypadku słownika najlepiej jest najpierw zakodować JSON. Możesz użyć simplejson.dumps () lub jeśli chcesz przekonwertować z modelu danych w App Engine, możesz użyć encode () z biblioteki GQLEncoder.
źródło
Miałem do czynienia z podobnym problemem i odpowiedź zaproponowana przez S.Lott działała dla mnie.
Chciałbym jednak tutaj zwrócić uwagę na poważne ograniczenie wdrażania . Jeśli planujesz umieścić kod JavaScript w innym pliku i dołączyć ten plik do szablonu. To nie zadziała.
Działa to tylko wtedy, gdy główny szablon i kod javascript znajdują się w tym samym pliku. Zespół django prawdopodobnie może rozwiązać to ograniczenie.
źródło
Walczyłem też z tym. Na pierwszy rzut oka wydaje się, że powyższe rozwiązania powinny działać. Jednak architektura django wymaga, aby każdy plik html miał własne renderowane zmienne (to znaczy
{{contact}}
jest renderowanecontact.html
, podczas gdy{{posts}}
przechodzi do np.index.html
Itd.). Z drugiej strony<script>
tagi pojawiają się po{%endblock%}
in,base.html
z którego pochodzącontact.html
iindex.html
dziedziczą. Zasadniczo oznacza to, że każde rozwiązanie, w tymmusi się nie powieść, ponieważ zmienna i skrypt nie mogą współistnieć w tym samym pliku.
Najprostszym rozwiązaniem, które w końcu wymyśliłem i działało dla mnie, było po prostu owinięcie zmiennej znacznikiem o id, a następnie odwołanie się do niej w pliku js, w ten sposób:
i wtedy:
i tylko to
<script src="static/js/somecode.js"></script>
siębase.html
jak zwykle. Oczywiście chodzi tu tylko o uzyskanie treści. Jeśli chodzi o bezpieczeństwo, wystarczy postępować zgodnie z innymi odpowiedziami.źródło
.textContent
zamiast.innerHTML
, ponieważ w przeciwnym razie jednostki, które zostaną zakodowane w HTML, również będą częścią zmiennej JS. Ale nawet wtedy może nie zostać odtworzone 1: 1 (nie jestem pewien).W przypadku obiektu JavaScript przechowywanego w polu Django jako tekst, który musi ponownie stać się obiektem JavaScript dynamicznie wstawianym do skryptu na stronie, musisz użyć zarówno
escapejs
iJSON.parse()
:Django
escapejs
poprawnie obsługuje cytowanie iJSON.parse()
konwertuje ciąg znaków z powrotem na obiekt JS.źródło
Zauważ, że jeśli chcesz przekazać zmienną do zewnętrznego skryptu .js, musisz poprzedzić tag skryptu innym tagiem skryptu, który deklaruje zmienną globalną.
data
jest zdefiniowany w widoku, jak zwykle wget_context_data
źródło
Używam tego w Django 2.1 i pracuję dla siebie, a ten sposób jest bezpieczny (odniesienie) :
Strona Django:
Strona HTML:
źródło
możesz złożyć cały skrypt, w którym zmienna tablicowa jest zadeklarowana w ciągu, w następujący sposób:
który wygeneruje ciąg w następujący sposób
po otrzymaniu tego ciągu musisz wysłać go do szablonu
w szablonie otrzymujesz go i interpretujesz w literacki sposób jako kod HTML, tuż przed kodem JavaScript, gdzie go potrzebujesz, na przykład
a poniżej znajduje się reszta kodu, pamiętaj, że zmienną, która ma być użyta w tym przykładzie, jest data2
w ten sposób zachowasz rodzaj danych, co w tym przypadku jest ustaleniem
źródło
aaa
będą zawierać tylko liczby, w przeciwnym razie możliwe jest XSS (wstrzyknięcie skryptu).Istnieją dwie rzeczy, które działały dla mnie wewnątrz Javascript:
i inne: w views.py
i w html:
źródło