Python dictionary to javascript

Passing Python Data to JavaScript via Django

I’m using Django and Apache to serve webpages. My JavaScript code currently includes a data object with values to be displayed in various HTML widgets based on the user’s selection from a menu of choices. I want to derive these data from a Python dictionary. I think I know how to embed the JavaScript code in the HTML, but how do I embed the data object in that script (on the fly) so the script’s functions can use it? Put another way, I want to create a JavaScript object or array from a Python dictionary, then insert that object into the JavaScript code, and then insert that JavaScript code into the HTML. I suppose this structure (e.g., data embedded in variables in the JavaScript code) is suboptimal, but as a newbie I don’t know the alternatives. I’ve seen write-ups of Django serialization functions, but these don’t help me until I can get the data into my JavaScript code in the first place. I’m not (yet) using a JavaScript library like jQuery.

8 Answers 8

n.b. see 2018 update at the bottom

I recommend against putting much JavaScript in your Django templates — it tends to be hard to write and debug, particularly as your project expands. Instead, try writing all of your JavaScript in a separate script file which your template loads and simply including just a JSON data object in the template. This allows you to do things like run your entire JavaScript app through something like JSLint, minify it, etc. and you can test it with a static HTML file without any dependencies on your Django app. Using a library like simplejson also saves you the time spent writing tedious serialization code.

Читайте также:  Web page links html

If you aren’t assuming that you’re building an AJAX app this might simply be done like this:

from django.utils import simplejson def view(request, …): js_data = simplejson.dumps(my_dict) … render_template_to_response("my_template.html", ) 
  

Note that the type of data matters: if my_data is a simple number or a string from a controlled source which doesn’t contain HTML, such as a formatted date, no special handling is required. If it’s possible to have untrusted data provided by a user you will need to sanitize it using something like the escape or escapejs filters and ensure that your JavaScript handles the data safely to avoid cross-site scripting attacks.

As far as dates go, you might also want to think about how you pass dates around. I’ve almost always found it easiest to pass them as Unix timestamps:

time_t = time.mktime(my_date.timetuple()) 

In JavaScript, assuming you’ve done something like time_t = > with the results of the snippet above:

my_date = new Date(); my_date.setTime(time_t*1000); 

Finally, pay attention to UTC — you’ll want to have the Python and Django date functions exchange data in UTC to avoid embarrassing shifts from the user’s local time.

EDIT : Note that the setTime in javascript is in millisecond whereas the output of time.mktime is seconds. That’s why we need to multiply by 1000

2018 Update: I still like JSON for complex values but in the intervening decade the HTML5 data API has attained near universal browser support and it’s very convenient for passing simple (non-list/dict) values around, especially if you might want to have CSS rules apply based on those values and you don’t care about unsupported versions of Internet Explorer.

let myWidget = document.getElementById("my-widget"); console.log(myWidget.dataset.viewMode); // Prints tabular somethingElse.addEventListener('click', evt => < myWidget.dataset.viewMode = "list"; >);

This is a neat way to expose data to CSS if you want to set the initial view state in your Django template and have it automatically update when JavaScript updates the data- attribute. I use this for things like hiding a progress widget until the user selects something to process or to conditionally show/hide errors based on fetch outcomes or even something like displaying an active record count using CSS like #some-element::after < content: attr(data-active-transfers); >.

Источник

Send Python information to a JavaScript file

I am new to Python and JavaScript and (attempting) to use cola.js. My HTML form sends information to Python, which turns it into an array of dictionaries.

Class_Name(ndb.Model): class_title = ndb.JsonProperty() def post(self): classname = self.request.get('classname') #user inputs 1 classname prereq = self.request.get('prereq') #user inputs 1 prereq new_dictionary = <> new_dictionary [classname] = prereq new_class = Class_Name(class_title = new_dictionary) #stores as a dictionary new_class.put() Class_data = Class_Name.query().fetch() #gets all instances of Class_Name *** code that goes in b/w sends back to input form if want to add more classes, else, goes to below code output = [] for a in Class_data: jsonprop = a.class_title extracted_output = json.dumps(jsonprop) output.append(extracted_output) template_vars= template = jinja2_environment.get_template('template/post.html') self.response.write(template.render(template_vars)) 

This is my basic code so far. I want to use cola.js to turn my information into a graph, basically mapping out each class with its prerequisites. However, the cola.js format is a JavaScript file that looks like this:

Is there any way I can tell JavaScript to get my Python array, and enter the info into the JavaScript file like this?

nodes_array = [] nodes_dict = <> links_array = [] links_dict = <> graph_array = [] #loops through every element for a in Class_data: jsonprop = a.class_title extracted_output = json.loads(jsonprop) for c_class, prereq in extracted_output.iteritems(): # for the links dictionary counter_link = 1 # creates nodes_dict['id'] = c_class #creates [ , ] nodes_array.append(nodes_dictionary) # creates links_dictionary[id] = counter_link counter_link++ links_dictionary[source] = c_class links_dictionary[target] = prereq # creates [] links_array.append(links_dictionary) #creating the format --> 'nodes': [ , , ]" #creating the format --> 'links': [ ]" graph[nodes] = nodes_array graph[links] = links_array 

Источник

Pass python dictionary to javascript

I have a Python + JS application connected to a PostgreSQL database. The database contains data about users in different countries, which is queried by the server.py file. The result of this query is a dictionary that would look something like this: <'US': 2, 'CA': 5>This dictionary needs to be passed to my map.js file, which populates a world map according to the country code (key) and volume (value). This dictionary updates with user activity, so it needs to be passed every time someone loads the map. How can I pass the data over? It seems like I need to create a JSON file. I’m not sure how to create that file within python or how to call it from javascript. I want to replace the hardcoded ‘var data’ values from map.js with my query results from country_count on server.py . my server.py :

@app.route("/map") def show_mapjs(): country_count = < "US": 0, "CA": 0, >country_code = session.get("country_code") for country_code, _ in country_count.items(): records_count = User_Records.query.filter_by(country_code=country_code).count() country_count[country_code] = records_count print(f"=== ") return country_count 

(US & CA are initialized at 0 and the records_count query updates the count as user activity increases over time.) my map.js :

fetch('/map') anychart.onDocumentReady(function () < var data = [ , ] var dataSet = anychart.data.set(data); var mapData = dataSet.mapAs(< description: 'description' >); var map = anychart.map(); 

1 Answer 1

Let’s get the work under way.

import json @app.route('/map') def show_mapjs(): country_count = < "US": 0, "CA": 0, >#place your own code here to get the data from the database# country_list = [] for country, count in country_count.items(): country_list.append() # Serializing json json_object = json.dumps(country_list) return json_object 

First, include the below js libs in the HTML, so the next code can use it.

Use the map js function as below,

   

You should do this way to avoid out-of-sync data loading and map rendering. This will ensure that the json is downloaded and then processed by the map.

Let me know if you have issues getting this working.

Источник

Converting Python objects to JavaScript for PyV8

The code above prints None, presumably because the data object is not transformed to a JSArray and thus data.length evaluates to undefined . Is there a reliable way to do the necessary conversion in PyV8 other than using JSON?

I’ve never used a global parameter this way in pyv8. I’d just write this as ctx = PyV8.JSContext() ctx.enter() ctx.locals.data = [<'a':1>] print ctx.eval(‘data.length’) Could you try this as a hello world before doing something more complex?

Thanks, but it’s not any better. ctx.locals.x = [<'a':1>]; ctx.eval(‘x.length’); ctx.eval(‘x[0].a’) prints None and 1.

1 Answer 1

Apparently PyV8 doesn’t correctly convert python lists to Javascript arrays, which leads my_list.length to return undefined , which is getting converted to None.

ctx = PyV8.JSContext() ctx.enter() ctx.locals.a = [] print ctx.locals.a #> [] print ctx.eval("a.length") #> None print ctx.eval("a[0].a") #> 1 ctx.locals.blub = print ctx.eval("blub.a") #> 1 print ctx.eval("Object.keys(blub)") #> a ctx.locals.blub = print ctx.eval("Object.keys(blub)") #> a print ctx.eval("blub.a") #> [1, 2, 3] ctx.locals.blub2 = [] print ctx.eval("blub2") #> [] print ctx.eval("blub2.length") #> None print ctx.eval("Array.isArray(blub2)") #> False print ctx.eval("typeof(blub2)") #> object print ctx.eval("blub2[0].a") #> [1, 2, 3] print ctx.eval("typeof(blub.a)") #> object print ctx.eval("Array.isArray(blub.a)") #> False 

The answer is to use PyV8.JSArray(my_list) . I’ve written the following helper functions for my project that deal with various little problems and make it easy to convert back and forth between python and js objects. These are targeted at a specific version of PyV8 however (which is the only version I can recommend, see discussion in the linked issues), so your results may vary if you use them as-is. Example usage:

ctx.locals.blub3 = get_js_obj() ctx.locals.blub4 = get_js_obj([1,2,3]) ctx.eval("blub3.a.length") #> 3 ctx.eval("blub4.length") #> 3 

And here are the functions.

def access_with_js(ctx, route): if len(route) == 0: raise Exception("route must have at least one element") accessor_string = route[0] for elem in route[1:]: if type(elem) in [str, unicode]: accessor_string += "['" + elem + "']" elif type(elem) == int: accessor_string += "[" + str(elem) + "]" else: raise Exception("invalid element in route, must be text or number") return ctx.eval(accessor_string) def get_py_obj(ctx, obj, route=[]): def dict_is_empty(dict): for key in dict: return False return True def access(obj, key): if key in obj: return objPython dictionary to javascript return None cloned = None if isinstance(obj, list) or isinstance(obj, PyV8.JSArray): cloned = [] temp = str(access_with_js(ctx, route)) #working around a problem with PyV8 r429 num_elements = len(obj) for index in range(num_elements): elem = obj[index] cloned.append(get_py_obj(ctx, elem, route + [index])) elif isinstance(obj, dict) or isinstance(obj, PyV8.JSObject): cloned = <> for key in obj.keys(): cloned_val = None if type(key) == int: #workaround for a problem with PyV8 where it won't let me access #objects with integer accessors val = None try: val = access(obj, str(key)) except KeyError: pass if val == None: val = access(obj, key) cloned_val = get_py_obj(ctx, val, route + Python dictionary to javascript) else: cloned_val = get_py_obj(ctx, access(obj, key), route + Python dictionary to javascript) clonedPython dictionary to javascript = cloned_val elif type(obj) == str: cloned = obj.decode('utf-8') else: cloned = obj return cloned def get_js_obj(ctx,obj): #workaround for a problem with PyV8 where it will implicitely convert python lists to js objects #-> we need to explicitely do the conversion. see also the wrapper classes for JSContext above. if isinstance(obj, list): js_list = [] for entry in obj: js_list.append(get_js_obj(ctx,entry)) return PyV8.JSArray(js_list) elif isinstance(obj, dict): js_obj = ctx.eval("new Object();") # PyV8.JSObject cannot be instantiated from Python for key in obj.keys(): try: js_objPython dictionary to javascript = get_js_obj(ctx,objPython dictionary to javascript) except Exception, e: # unicode keys raise a Boost.Python.ArgumentError # which can't be caught directly: # https://mail.python.org/pipermail/cplusplus-sig/2010-April/015470.html if (not str(e).startswith("Python argument types in")): raise import unicodedata js_obj[unicodedata.normalize('NFKD', key).encode('ascii','ignore')] = get_js_obj(ctx,objPython dictionary to javascript) return js_obj else: return obj 

Источник

Оцените статью