Is their any way to define django variable in template by javascript variable
you can do like this in your script.
<script type="text/javascript">
var a = "{{yourVariable}}";
</script>
and store it as script variable
I suppose you have to do few thing before delcare any django variable in temple by using javascript:
step 1: views.py
def XYZfunc(request, abc):
try:
some code here...
content = {'abc': abc}
return render(request, 'ProjectName/xyz_html_page.html', content)
except(ObjectDoesNotExist, KeyError, ValueError):
content = {'abc': abc}
return render(request, 'ProjectName/xyz_html_page.html', content)
step 2: urls.py (optional)
url(r'^ProjectName/xyz_htmlpage_name/(?P<abc>[A-Z]+)/$', views.XYZfunc, name="abc"),
(please note: if you are sending value through html url from views.py
then use urls.py and if value is string then (?P[A-Z]+) )
Step 3: xyz_html_page.html
<script type="text/javascript">
var u = "{{abc}}";
</script>
i hope it might help you.
Related
First of all, I will like to say this is my first question here! (pardon me if this is redundant or duplicated)
I am having some problems with calling JS scripts from Django template:
{% for suggestion in suggestions %}
<img class="catalogue-poster" src="{{ suggestion.poster }}" alt="Portada" onclick="
document.getElementById('{{form.title.auto_id}}').value = '{{suggestion.title}}'
document.getElementById('{{form.year.auto_id}}').value = '{{suggestion.year}}'
document.getElementById('{{form.director.auto_id}}').value = '{{suggestion.director}}'
document.getElementById('{{form.rating.auto_id}}').value = '{{suggestion.rating}}'
document.getElementById('{{form.poster.auto_id}}').value = '{{suggestion.poster}}'
document.getElementById('{{form.trailer.auto_id}}').value = '{{suggestion.trailer}}'
document.getElementById('{{form.synopsis.auto_id}}').value = '{{suggestion.synopsis}}'
document.getElementById('{{form.cast.auto_id}}').value = '{{suggestion.cast}}'
" />
{% endfor %}
So, first of all, how can I declare a function outside. I'm a C developer, sorry for my ignorance.
I've tried to create a script outside, such as
<script>
function foo() {
console.log('Hey');
});
</script>
And invoke it this way:
<img class="catalogue-poster" src="{{ suggestion.poster }}" alt="Portada" onclick="foo()"/>
But this simple thing that works on pure HTML, with django templates does not seem to work...
On the other hand, the real question was, is there a way to access a Django variable passed in render with a js variable?
Such as:
const jsVariable = 'title';
document.getElementById('{{form.jsVariable.auto_id}}').value = '{{suggestion.jsVariable}}'
I have not found any way to accomplish this, maybe there is another great idea!
I have tried one example. where is send a variable from python script and access its value in JavaScript
1) In views.py
from django.shortcuts import render
def home_view(request):
var_name = 'hello'
return render(request, 'home.html', {'var_name':var_name})
2) In html file(home.html)
<html>
<h1>Home Page</h1>
<input type="button" value="Submit" onclick="fun()">
<script>
function fun(){
console.log('hello world '+ '{{var_name}}' );
}
var temp = '{{var_name}}';
console.log(temp + 20);
</script>
</html>
If i click submit button ( hello world hello ) is printed in console.
I stored value of var_name in temp which can be further used.
From your example, it looks you want to programmatically access a Django model's attribute in Javascript.
The main takeaway is that you first need to expose the data structure you want to access (i.e. the model) in Javascript.
Here's a simple, redacted, proof-of-concept you can try.
import json
def my_view(request):
obj = MyModel.objects.get(1)
obj_dict = {
"foo": obj.foo,
"bar": obj.bar,
}
return render(request, 'my_view.html', context={'obj_json': json.dumps(obj_dict)} )
<script>
var obj = {{obj_json}};
var field = 'foo';
console.log(obj[field]);
Check out Convert Django Model object to dict with all of the fields intact for a run-down on options to serialize Django models into dictionaries.
Well, finally I found a solution for both exposed problems.
First of all, the script function I declared was not working because it seems that there is an attribute called autocomplete (see autocomplete HTML attribute)
So, you can not declare a JavaScript function with this name, my fail.
Uncaught TypeError: autocomplete is not a function
Finally, the simple solution I found was passing an array of dicts to the template:
return render(request, 'example.html', {'form': form, 'suggestions': suggestions })
And then in the template:
{% for suggestion in suggestions %}
<img src="{{ suggestion.poster }}" onclick="autocompleteMovie({{suggestion}});" />
{% endfor %}
<script>
function autocompleteMovie(suggestion){
for (let field in suggestion)
document.getElementById('id_' + field).value = suggestion[field]
}
</script
Which, comparing it with the question, really simplifies the problem.
I am using Thymeleaf as template engine. How I pass a variable from Spring model to JavaScript variable?
Spring-side:
#RequestMapping(value = "message", method = RequestMethod.GET)
public String messages(Model model) {
model.addAttribute("message", "hello");
return "index";
}
Client-side:
<script>
....
var m = ${message}; // not working
alert(m);
...
</script>
According to the official documentation:
<script th:inline="javascript">
/*<![CDATA[*/
var message = /*[[${message}]]*/ 'default';
console.log(message);
/*]]>*/
</script>
Thymeleaf 3 now:
Display a constant:
<script th:inline="javascript">
var MY_URL = /*[[${T(com.xyz.constants.Fruits).cheery}]]*/ "";
</script>
Display a variable:
var message = [[${message}]];
Or in a comment to have a valid JavaScript code when you open your template file in a static manner (without executing it at a server).
Thymeleaf calls this: JavaScript natural templates
var message = /*[[${message}]]*/ "";
Thymeleaf will ignore everything we have written after the comment and before the semicolon.
More info: http://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html#javascript-inlining
var message =/*[[${message}]]*/ 'defaultanyvalue';
According to the documentation there are several ways to do the inlining.
The right way you must choose based on the situation.
1) Simply put the variable from server to javascript :
<script th:inline="javascript">
/*<![CDATA[*/
var message = [[${message}]];
alert(message);
/*]]>*/
</script>
2) Combine javascript variables with server side variables, e.g. you need to create link for requesting inside the javascript:
<script th:inline="javascript">
/*<![CDATA[*/
function sampleGetByJquery(v) {
/*[+
var url = [[#{/my/get/url(var1=${#httpServletRequest.getParameter('var1')})}]]
+ "&var2="+v;
+]*/
$("#myPanel").load(url, function() {});
}
/*]]>*/
</script>
The one situation I can't resolve - then I need to pass javascript variable inside the Java method calling inside the template (it's impossible I guess).
MAKE sure you have thymleaf on page already
//Use this in java
#Controller
#RequestMapping("/showingTymleafTextInJavaScript")
public String thankYou(Model model){
model.addAttribute("showTextFromJavaController","dummy text");
return "showingTymleafTextInJavaScript";
}
//thymleaf page javascript page
<script>
var showtext = "[[${showTextFromJavaController}]]";
console.log(showtext);
</script>
I've seen this kind of thing work in the wild:
<input type="button" th:onclick="'javascript:getContactId(\'' + ${contact.id} + '\');'" />
If you use Thymeleaf 3:
<script th:inline="javascript">
var username = [[${session.user.name}]];
</script>
If you need to display your variable unescaped, use this format:
<script th:inline="javascript">
/*<![CDATA[*/
var message = /*[(${message})]*/ 'default';
/*]]>*/
</script>
Note the [( brackets which wrap the variable.
Another way to do it is to create a dynamic javascript returned by a java controller like it is written here in the thymeleaf forum: http://forum.thymeleaf.org/Can-I-use-th-inline-for-a-separate-javascript-file-td4025766.html
One way to handle this is to create a dynamic javascript file with the
URLs embedded in it. Here are the steps (if you are using Spring MVC)
#RequestMapping(path = {"/dynamic.js"}, method = RequestMethod.GET, produces = "application/javascript")
#ResponseStatus(value = HttpStatus.OK)
#ResponseBody
public String dynamicJS(HttpServletRequest request) {
return "Your javascript code....";
}
Assuming request attribute named "message":
request.setAttribute("message", "this is my message");
To read it in the html page using Thymeleaf template:
<script>
var message = "[[${message}]]";
alert(message);
</script>
I want to pass a queryset from a view to a javascript function throught the template:
my view.py:
def myview(request):
lista=Mymodel.objects.filter(tipo=mytipo)
context_dict['lista']=lista
return render(request, 'mytemplate.html', context_dict)
my template.html:
<script>
<!--
window.onpageshow = function() {
myfunction('{{lista}}');
};
-->
</script>
my javascript.js:
function myfunction(lista) {
for (i=0; i<lista.length; i++) {
console.log(lista[i].name)
}
}
The problem is that lista become a string. I tried with JSONEncoder but i'm not sure how to use. I would like to avoid JsonResponse because I want to use that view for my template (if possible).
Edit:
There's a problem with the solution proposed in the answer:
TypeError: Python object is not JSON serializable
and the solution proposed in this link doesn't works either (can't find _meta attribute called by model_to_dict).
JSON.parse doesn't works
SyntaxError: missing ) after argument list
and the problem seem to be between one path and the other:
myfunction(JSON.parse('['/mypath/myimage.png', '/otherpath/otherimage.png', 'etc... ']'));
Also in the template you must add |safe.
Luckly I need a list of string so:
my view.py:
def myview(request):
lista=Mymodel.objects.filter(tipo=mytipo)
lista_formatted=[]
for elem in lista:
lista_formatted.append('/media/'+str(elem.myfield))
lista_formatted=json.dumps(lista_formatted)
context_dict['lista']=lista_formatted
return render(request, 'mytemplate.html', context_dict)
my template.html:
<script>
<!--
window.onpageshow = function() {
myfunction({{lista|safe}});
};
-->
</script>
change the line below
context_dict['lista']=json.dumps(lista) //note json.dumps() wraps it
Remove the quotes around here:
<script>
<!--
window.onpageshow = function() {
myfunction({{lista}});//<--quote removed!
};
-->
</script>
You need to first pass a queryset as a list of dictionary representing instances to the template. In order to do so in the views.py:
def myview(request):
lista = Mymodel.objects.filter(tipo=mytipo)
context_dict['lista'] = list(lista.values())
# Also you can instead also pass the needed parameters to 'values' function, like this:
# context_dict['lista'] = list(lista.values('field1', 'field3'))
return render(request, 'mytemplate.html', context_dict)
Then you need to define a js variable in the template and pass the value of lista to it. So in the mytemplate.html file:
<script>
window.onpageshow = function() {
myfunction({{ lista|safe }}); <!-- Don't forget to use 'safe' templatetag! -->
};
</script>
This way you don't need to use any third-party package.
I'm working on a Python package that uses Tornado to send data to the browser for visualization. In order to do this, I want the users to be able to write multiple arbitrary modules for the server to render together on a single page -- including each module's own JavaScript.
However, by default, the Tornado's UIModule class's embedded_javascript() method only appends JavaScript to <script>...</script> once per module class. I'm hoping there is a simple way to embed multiple pieces of JS, one for every UIModule (or another way to get the same effect).
Here's a minimal example of what I'm talking about:
import tornado.ioloop
import tornado.web
import tornado.template
class Element(tornado.web.UIModule):
'''
Module to add some custom JavaScript to the page.
'''
def render(self, element):
self.js_code = element.js_code
return ""
def embedded_javascript(self):
return self.js_code
class InterfaceElement(object):
'''
Object to store some custom JavaScript code.
'''
def __init__(self, js_code):
'''
Args:
js_code: Some JavaScript code in string form to add to the page.
'''
self.js_code = js_code
class MainPageHandler(tornado.web.RequestHandler):
def get(self):
elements = self.application.modules
self.render("uitest_template.html", app_name="Testing", elements=elements)
class ThisApp(tornado.web.Application):
def __init__(self, modules):
self.modules = modules
main_handler = (r'/', MainPageHandler)
#settings = {"ui_modules": {"Element": Element}}
settings = {"ui_modules": {"Element": Element},
"template_path": "ui_templates"}
super().__init__([main_handler], **settings)
# Create two objects with some custom JavaScript to render
module_1 = InterfaceElement("var a = 1;")
module_2 = InterfaceElement("var b = 2;")
app = ThisApp([module_1, module_2])
app.listen(8888)
tornado.ioloop.IOLoop.instance().start()
And the template for uitest_template.html is just
<!DOCTYPE html>
<head>
<title> Hello World </title>
</head>
<body>
{% for element in elements %}
{%module Element(element) %}
{% end %}
</body>
The rendered page then includes a <script> tag in body that is:
<script type="text/javascript">
//<![CDATA[
var b = 2;
//]]>
</script>
And what I want is:
<script type="text/javascript">
//<![CDATA[
var a = 1;
var b = 2;
//]]>
</script>
Or something like it. Any ideas?
Added - my solution
Based on the answer below, here's how I ended up handling it:
import tornado.ioloop
import tornado.web
import tornado.template
class InterfaceElement(object):
include_js = [] # List of .js files to include
js_code = '' # JavaScript string to include
def __init__(self, include_js=[], js_code=''):
self.include_js = include_js
self.js_code = js_code
class MainPageHandler(tornado.web.RequestHandler):
def get(self):
self.render("modular_template.html",
includes=self.application.include_js,
scripts=self.application.js_code)
class ThisApp(tornado.web.Application):
def __init__(self, modules):
# Extract the relevant info from modules:
self.modules = modules
self.include_js = set()
self.js_code = []
for module in self.modules:
for include_file in module.include_js:
self.include_js.add(include_file)
if module.js_code != '':
self.js_code.append(module.js_code)
main_handler = (r'/', MainPageHandler)
settings = {"template_path": "ui_templates",
"static_path": "ui_templates"}
super().__init__([main_handler], **settings)
module_1 = InterfaceElement(js_code="var a = 1;")
module_2 = InterfaceElement(include_js=["test.js"], js_code="var b = 1;")
app = ThisApp([module_1, module_2])
app.listen(8888)
tornado.ioloop.IOLoop.instance().start()
Which goes with the following template:
<!DOCTYPE html>
<head>
<title> Hello world </title>
</head>
<body>
<!-- Script includes go here -->
{% for file_name in includes %}
<script src="/static/{{ file_name }}" type="text/javascript"></script>
{% end %}
<script type="text/javascript">
// Actual script snippets go here.
{% for script in scripts %}
{% raw script %}
{% end %}
</script>
</body>
embedded_javascript and related methods are (effectively) class-level methods; they must return the same value for any instance of the class. (They're intended to be a kind of dependency-management system, so you can load a piece of javascript only on pages that include a module that needs it)
The only thing that is allowed to vary per instance is the output of render(), so to embed multiple pieces of javascript you should include the script tag in the result of your render() method.
I just need your help about my code. My problem is how can I access smarty variable within jquery or javascript file? Becuase my smarty variable is a URL request from my controller. And I need to use that variable for creating validation. Here's my code.
{$get.search_by} {**works without error**}
{literal}
<script type="text/javascript">
$(document).ready(function(){
var dispatch = "{$get.search_by}"; //can't access
var new_class = "it3 ir3 il3 jt10 jr05 jl05 kt03 kr04 kl04";
var old_class = "it3 ib3 il3 jt05 jb05 jl10 kt04 kb04 kl03";
var toggleState = true;
//could not access
if(dispatch == companies.catalog){
alert("catalog");
}else{
alert("product search");
}
console.log(dispatch);
Try this code
var dispatch = '{/literal}{$get.search_by}{literal}'
To make things cleaner, you can move the {literal} tag down and also escape the $get.search_by variable (in case search_by may have a string with a quote i.e. "let's try"):
<script type="text/javascript">
var dispatch = '{$get.search_by|escape:'javascript'}';
{literal}