Django variable isnt recognized by javascript - javascript

I serialized an object of mine using the built in method with django and then passed it into my template. When I put {{goals}} in the html, the data shows perfectly. However, when I try to access it through a js script, it doesnt work. Why is this? I alerted it and it keeps coming as undefined.
#Python Views
def characterscreen(request):
goals = serializers.serialize("json", Goal.objects.filter(userprofile=userprof))
#goals = Goal.objects.filter(userprofile=userprof).values()
return render_to_response('levelup/characterscreen.html', {'goals': goals}, context_instance=RequestContext(request))
Python Model
class Goal(models.Model):
title = models.CharField(max_length = 30)
userprofile = models.ForeignKey(UserProfile)
type = models.CharField(max_length = 5)
def __unicode__(self):
return str(self.title)
JS File
$("body").onload = load_goals();
function load_goals (){
alert(goals);}
HTML
<!DOCTYPE html>
<html>
<head>
{% load staticfiles %}
<title>{% block title %}{% endblock %}</title>
<link rel="stylesheet" type="text/css" href="{% static 'levelup/style.css' %}" />
{% block header %}{% endblock%}
</head>
<body>
<div id="headercontainer">
<div id="header">
</div>
</div>
{% block content %}{% endblock %} <script type="text/Javascript" src="http://code.jquery.com/jquery-1.10.1.min.js"></script> <script type="text/Javascript" src="http://code.jquery.com/jquery-migrate-1.2.1.min.js"></script>
<script type="text/javascript">goals = "{{ goals|safe }}"</script>
<script type="text/Javascript" src="{% static 'levelup/script.js' %}"></script>
</body>
</html>
I tried removing the quotes and now the variable is just alerting a [object Object],[object Object] when I do alert(goals)

That's because external .js files aren't processed like html files are. This only works with inline scripts. So you should put this in your HTML file:
<script type="text/javascript">
goals = "{{ goals }}"
</script>
<script type="text/javascript" src="script.js" />
Then you can use the goal variable in script.js.
EDIT:
JSON always uses double quotes, so you'll have to put single quotes around it. Additionally, althrough a JSON string actually represents a real Javascript object when used without quotes, it's best to parse the JSON before you use it. As you seem to be using jQUery, use:
goals = $.parseJSON('{{ goals|safe }}')

Related

JavaScript only runs when both the code is inside the HTML and is called externally with <script src=...>

My JavaScript code only runs when the code is both inside the HTML file and called externally via
<script type="text/javascript" src="{{ url_for('static', filename='index.js') }}"></script>
<script>
var scroller = document.querySelector("#scroller");
...
</script>
I am using Flask and Jinja, with a file structure of:
/app
/static
index.js
/templates
base.html
myfile.html
routes.py
__init__.py
...
The code inside index.js is the exact same code between the <script> tags inside the HTML.
In terms of jinja and using block tags, base.html:
<body>
{% block content %}
<!-- typical HTML stuff here -->
{% endblock %}
<!-- some Bootstrap tags -->
<script ... ></script>
{% block script %}{% endblock %}
</body>
myfile.html:
<body>
...
{% block script %}
<script type="text/javascript" src="{{ url_for('static', filename='index.js') }}"></script>
{% endblock %}
<script>
...
</script>
The code itself works, and it worked not too long ago without this issue; I don't know what I changed to cause this, nor can I even imagine what could cause this. If there is more code that is required, I can easily share it.
Is there something I not understanding?
To note: I have had a similar issue trying to including external JavaScript code inside my HTML; at one point it wouldn't work, then it did, now it behaves the way I have described.
To further note: I have another .html file with its own external .js file that works fine.
Mr.#JakeJackson, Script in externl file never requires the same content to be available inside your inline code.
May be you are trying to process some elements and your script got executed before those elements are mounted to the document object.
A lazy solution to that problem is moving the external file linking tag to the bottom your HTML.Body.
OR
You can use defer attribute to your script element https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script
OR
If you have some libraries like jQuery included in your page, You can use the document.ready implementations in that
OR
you can implement your own document.ready like below
function myReady() {
return new Promise(function(resolve) {
function checkState() {
if (document.readyState !== 'loading') {
resolve();
}
}
document.addEventListener('readystatechange', checkState);
checkState();
});
};
myReady().then(function() {
// Put your app custom code here
});

Javascript queryselectors not reading classes and ID when used in Django project

When I am working outside Django file, everything works fine with javascript reading classes and Ids like
document.querySelector('.class_name').addEventListener
But when loaded in Django projects it gives an error that eventlistner can't read NULL.
{% comment %} css file for contacts.html {% endcomment %}
<script type="text/javascript" src="{% static 'info/js/for_recrs.js' %}"></script>
<link href="{% static 'info/css/for_recrs.css' %}" rel="stylesheet" type="text/css" />
{% endblock %}
Actually if you are declaring JS file in head, it will read it at that time itself without going through the HTML file. So, it reads null value of classes and ID.
To avoid that you can declare script file just beforeend of body.
OR
Use
window.onload = function() {
// do your stuff here.
}
It solved mine problem.

django use of templates views and ajax

Sorry I couldn't come with a more precise topic title and I must admit I'm still pretty new Django.
I am trying to work with Ajax and templates with splitted views but I can't achieve what I want, one way or another.
My goal is to be able to work with rendered templates and jquery hide/show instructions but I'm failing at some point.
Here is my urls.py:
from django.urls import path
from django.conf.urls import url
from . import views, inventory
urlpatterns = [
path('', views.index, name='index'),
url(r'^inventory', inventory.inventory, name='inventory'),
url(r'^buildInventory', inventory.buildInventory, name='buildInventory'),
]
My views index renders a templated "index.html" (there is a context that I removed for the illustration):
def index(request):
return render(request, 'myapp/index.html', context)
My index.html file :
{% extends "base.html" %}
{% load static %}
{% block delivery_form %}
<div id="mainblock">
....
</div>
{% endblock %}
And my base.html mostly contains my statics & headers:
{% load static %}
<!doctype html>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<link rel="shortcut icon" type="image/png" href="http://web-iec/favicon.ico"/>
<link rel="stylesheet" type="text/css" href="{% static 'myapp/css/nice.css' %}">
<script type="text/javascript" src="{% static 'myapp/js/jquery.js' %}" ></script>
<script type="text/javascript" src="{% static 'myapp/js/jquery-ui.js' %}" ></script>
<script type="text/javascript" src="{% static 'myapp/js/inventory.js' %}" ></script>
<script type="text/javascript" src="{% static 'myapp/js/homepage.js' %}" ></script>
</head>
<body>
<div class="navBar">
<span class="navBtn" id="listDeplVer" title="Inventory">Inventory</span>
</div>
<div style="min-height: 100%;margin-bottom: -20px;">
{% block delivery_form %}
{% endblock %}
{% block inventory %}
{% endblock %}
</div>
</body>
</html>
Now what I'm trying to achieve, within my inventory.js I've got an onclick event that I'm trying to use to hide the home page content and replace it by the rendered html from my inventory.py view with associated html:
my inventory.py:
def inventory(request):
return render(request, 'myapp/inventory.html')
and my inventory.html:
{% extends "base.html" %}
{% load static %}
{% block inventory %}
<div id="inventoryblock">
// html
</div>
{% endblock %}
Finally my inventory.js is looking like:
$(document).ready(function () {
$( "#listDeplVer" ).click( function () {
$.ajax({
type: 'GET',
dataType: 'html',
url: '/myapp/inventory',
beforeSend: function(){
$("#mainblock").fadeOut();
},
success : function(output){
$("#inventoryblock").html(output);
},
});
});
So like I said I was expecting that onclick my page's content is replaced by the rendered inventory page, but this is not working.
When using the web developper tools, if I open the XHR request for the inventory in a new tab it work just fine, so I assume I'm doing something the wrong way.
Before merging everything in one single file (js, views, html & so on) I wanted to ask if there is way to have something similar to work ?
Thank you for your help
Your source page doesn't have an "inventoryblock" div. That's only in the page you're loading via Ajax. So when your success function runs, it doesn't know where to put the output.
You need to put an empty div with id "inventoryblock" in your index.html.
Also, your inventory.html probably shouldn't inherit from anything. You don't need the full HTML file with the head block etc, you just want the fragment containing the contents of inventoryblock that you can insert into the requesting page. Remove everything other than the relevant HTML itself.

Django: How to keep JavaScript code separate in static folder when it uses a python variable

I have a bunch of canvases that needs to be rendered. I don't want put the
JavaScript code in a python loop, because I feel it's bad practice
home.html
{% load staticfiles %}
<head>
<script type="text/javascript" src="{% static
'canvas/canvasrender.js' %}"></script>
</head>
{% for canvas in user_canvas_set %}
<canvas class = "canvas" id="{{canvas.id}}" width="400" height="200"
canvas_post= ""{{canvas.canvas_post}}"" >
Your browser does not support the HTML5 canvas tag.</canvas>
**<script>
canvasrenderNP.canvaswrite("{{canvas.id}}","{{canvas.canvas_post}}")
</script>**
{% endfor %}
I made a custom function that returns an array of the users canvas ids, because I use the canvas id as the id for the canvas element.
home.html
<script>
alert("{{user_canvas_ids}}")
</script>
I get the desired output:
[247, 248, 251, 252]
Now when I put this in a static file
canvasrender.js
alert("{{user_canvas_ids}}")
then load it into
home.html
{% load staticfiles %}
<head>
<script type="text/javascript" src="{% static
'canvas/canvasrender.js' %}"></script>
</head>
output:
"{{user_canvas_ids}}"
I am confused to as what is going on. I thought that the script tag inserts the js file in between the "<script> </script>"
I know I can make a element like so and get the attribute, but I feel like that is not good practice, or is it fine?
<p id="canvas_ids" canvas_ids ="{{user_canvas_ids}}"> </p >
Is there anything else I can do so that I can avoid writing JavaScript code
in the HTML file?
Why this is not a duplicate question. It does not have anything about why the linked js file in the html page can not keep reference to the python variable. But if the JavaScript is coded in the html page it can
As you mentioned in your own comment, you can save user_canvas_id in a js variable in home.html and access it in your js file. Something like this:
<head>
<script>var user_canvas_id = "{{ user_canvas_id }}"</script>
<script type="text/javascript" src="{% static 'canvas/canvasrender.js' %}"></script>
</head>
I am confused to as what is going on. I thought that the script tag inserts the js file in between the "<script> </script>"
Kinda, but this is done client-side, by the browser who has no idea about the special meaning of curly braces in Django templates.
And static in the context of Django means just that: That Django serves that file as-is, without running it through the template engine. (Which wouldn't help here anyway, as for the JavaScript file in isolation, the value of user_canvas_ids would be unknown, so the template engine couldn't substitute anything useful for it.)

js scripts not loading in jinja2 template

I have a situation where, replacing a url string "/CreditHistory/10216" with a jinja2 variable {{creditNumbers|safe}}, messes up the loading of javascript files. More specifically, this works;
{% block Scripter %}
<script type="text/javascript" src="./static/assets/js/crossfilter/crossfilter.js"></script>
<script type="text/javascript" src="./static/assets/js/d3/d3.js" charset="utf-8"></script>
<script type="text/javascript" src="./static/assets/js/dc.js/dc.js"></script>
<script type="text/javascript" src="./static/assets/js/queue/queue.js"></script>
<script src='./static/assets/js/graphsFordringer.js' type='text/javascript' charset="utf-8"></script>
<script type="text/javascript">
queue().defer(d3.json, "/CreditHistory/10216").await(makeGraphs);
</script>
{% endblock %}
But, this does not;
{% block Scripter %}
<script type="text/javascript" src="./static/assets/js/crossfilter/crossfilter.js"></script>
<script type="text/javascript" src="./static/assets/js/d3/d3.js" charset="utf-8"></script>
<script type="text/javascript" src="./static/assets/js/dc.js/dc.js"></script>
<script type="text/javascript" src="./static/assets/js/queue/queue.js"></script>
<script src='./static/assets/js/graphsFordringer.js' type='text/javascript' charset="utf-8"></script>
<script type="text/javascript">
queue().defer(d3.json, "{{creditNumbers|safe}}").await(makeGraphs);
</script>
{% endblock %}
The errors that gets thrown in the web-browser implies that none of the javascript files get loaded. One of them is for example that queue is not a defined function.
What is also apparent is that the "{{creditNumbers|safe}}" variable does load to "/CreditHistory/10216". So, in short the variable loading seems to break the javascript loading. Not that I have found reference to similar issues in the documentation, so that probably is not what is happening.
EDIT:
It now seems that I have misunderstood the entire situation. It looks like it is the way that the jinja2 template variable is declared in the app.py file that is the root cause.
The #app.routecode that is failing is;
#app.route('/KundeFordringer/<int:KundeNr>')
def fordringer(KundeNr):
jsonSti = "/CreditHistory/"+str(KundeNr)
return render_template("fordringer.html", creditNumbers=jsonSti)
However, if I change the code to the following, it works fine;
#app.route('/KundeFordringer')
def fordringer():
return render_template("fordringer.html", creditNumbers="/CreditHistory/10216")
As mentioned previously, viewing the source code from the web browser, one could see that the "/CreditHistory/10216"was loaded when using the first #app.route declaration. But apparently something is, never the less, off with that way of doing it.
Any help would be greatly appreciated
The loading of the javascript files is relative to the current url.
Basically if you are browsing
http://mywebsite.com/KundeFordringer/456
Then the browser is going to try to load those files:
http://mywebsite.com/KundeFordringer/456/static/assets/js/crossfilter/crossfilter.js
http://mywebsite.com/KundeFordringer/456/static/assets/js/d3/d3.js
http://mywebsite.com/KundeFordringer/456/static/assets/js/dc.js/dc.js
http://mywebsite.com/KundeFordringer/456/static/assets/js/queue/queue.js
What you want is probably
http://mywebsite.com/static/assets/js/crossfilter/crossfilter.js
http://mywebsite.com/static/assets/js/d3/d3.js
http://mywebsite.com/static/assets/js/dc.js/dc.js
http://mywebsite.com/static/assets/js/queue/queue.js
Their might be a problem either with your script tags:
<script type="text/javascript" src="./static/assets/js/dc.js/dc.js"></script>
That needs to be renamed
<script type="text/javascript" src="/static/assets/js/dc.js/dc.js"></script>
Or a problem with your static_url_path.

Categories

Resources