Pass a list of string from Django to Javascript - javascript

My Django objects have an attribute "City". I'm trying to get a list of cities and catch it in the template with Jquery (to use in a chart on the X axis).
My problem is that I can't get rid of the unicode and quote for a list.
(I manage to do it for one single value). Instead I'm stucked with this:
["[[u'Paris'], [u'Lyon']]"]
I've tried tons of things, included JSON. No success.
My view:
(actually, one of many try..)
def barchart1(request):
city_array =[]
for i in [1,MyObject.objects.count()]:
objet = get_object_or_404(MyObject, pk=i)
cities = [objet.city.city_name]
city_array.append(cities)
return render (request, 'plot3/plot_page.html', {"city_array" : city_array})
My JS:
<script type="text/javascript">
var cities = ["{{ city_array }}"];
</script>
Here is how JS read the context sent by the view
["[[u'Paris'], [u'Lyon']]"]
Here is what I would like to get
['Paris', 'Lyon']
It MUST be something simple but I just couldn't figure out how to do it.
Others posts don't deal with a list of string.
Any idea of what should I do?

When you do {{ city_array }} in your template, your list is converted to a string. This is done by calling repr() on the list, which recursively calls repr() on its contents. Because your strings are unicode, you see those unicode literals, u'Paris'.
The "correct" way to do this is to encode your data to json, for example in your view:
import json
# ...
json_cities = json.dumps(city_array)
# ...
return render (request, 'plot3/plot_page.html', {"city_array" : json_cities})
and then do
var cities = {{ city_array|safe }};
in the template.
Please note: don't use this for user-controller data! See the XSS Cheat Sheet by OSWASP and the discussion on Django ticket 17419 for further information. To prevent XSS, you could use something like the SafeJSONEncoder from the django-cms project.

Related

Issue formatting a list of dictionaries to be used by javascript

I'm fairly new to Django, and I'm looking for the ideal way to handle data queried from GraphQL and creating HTML elements from the data to display on my website.
I've been generating a list of dictionaries from product information, all of which have "id", "name", "price", etc. and passing them onto my template as is.
On the template I can traverse the list with a for loop and the items correctly display within a p element as {'id': '...', 'title': '...' } However on js what I see is a string containing [{'id':... What's the ideal way to generate a list of dictionaries usable by JS from this string?
Also, declaring a variable with the filter |safe as such:
var products = "{{data|safe}}";
generates an Unexpected Identifier error for some reason.
You can look into using the json_script template tag:
{{ value|json_script:"json-data" }}
This will render into a tag like so:
<script id="json-data" type="application/json">{"key": "value"}</script>
You can use it in javascript by writing:
const value = JSON.parse(document.getElementById('json-data').textContent);
Reference: Django docs- json_script
Another option would be to return a JsonResponse for an ajax request made using javascript.

Django Trying to save my Array to the model

I have the following data coming from the
manager_item = request.POST.getlist(manager_type_item)
in my views:
['{"id":"1","title":"Bedroom"},{"id":"2","title":"Taps"}, {"id":"3","title":"Living Room"}']
Basically each one of these are {"id":"1","title":"Bedroom"} will need t be added into the model:
index = 0
for index, item in enumerate(json.loads(manager_item)):
print(item['id'])
print(item['title'])
But I not 100% sure the route to go. Hope someone can assist me. Still learning. I know how to save to the model I just need help with getting the data needed.
In fact this looks like a comma separated list of JSON blobs. We can convert this to a list as follows:
from json import loads as jsonload
data = jsonload('[{}]'.format(request.POST[manager_type_item]))
These are JSON blobs, so we can decode these with json.loads, and then process these, like:
for itm in data:
Tag.objects.create(**itm)
or in case the dictionaries contain other elements that do not belong to the model:
for itm in data:
Tag.objects.create(id=itm['id'], title=itm['title'])
We thus use a mapping to convert these JSON blobs first to there relevant vanilla Python objects (here dictionaries that map strings to strings), and then turn the given elements into a Tag (or something else).
Or in bulk:
Tag.objects.bulk_create([Tag(**itm) for itm in data])

Can you do more than iterate through an array in Laravel Blades?

I have passed an array ($players) to my view, and I can easily iterate over it using #foreach within the blade, but what I am actually trying to do is check the entire array for a certain players name, then output all of his data in the blade. I plan on doing this using a dialog box. This would be all well and good if I was using a search feature, or something like that, but I am trying to just use jQuery-UI's Dialog() and some Javascript. Whenever a players name is hovered over, I'd like to run that query and display his stats.
Is it possible to search through an array in such a way in blade templating? I figure I can just compact all of the players into their own array and then pass it to the view, but this seems like too much work (in the sense that I feel this can be more automated). As of now, it's only 17 players, but I'd like this to work if it was 100 players.
Thanks
Blade templates are rendered server-side and it sounds like you want to search through the data based on a user doing something, i.e. on the client-side.
A crude way of doing this would be to write all your player data to into a javascript variable:
<script>
var playerData = {!! $player_data !!};
</script>
Where $player_data is passed to the view your PHP script.
Then you can search through data with javascript.
In your view you could use laravel's helper function to filter your array by a specific player's name..yet im not sure if this is best way to get your result
//in this case its returning only the values that are strings
(example on laravels documentation)
$array = array_where($array, function ($key, $value) {
return is_string($value);
});

How to assign javascript variable with a django template variable that consist of multiple lines?

I'm fetching data from mysql longtext field. And it can contain new lines.
This data is passed to the template where I assigns this longtext data to a javascript variable. The problem I get now is that it will complain about unterminated string literal.
Which is because it tries to assign data in this way
$("#id_review").val("kokokoeoarkgeorkgeorkgeorkg
er
g
gerag
earg
ea
gae
gr
er
gea
g
ear
ge
gae
rg
eagr
kok")
I tried to write a custom filter that will add "+ to the end of each line, but it didn't work out too well. So I wonder can this problem be fixed somehow?
My attempt on a filter
#register.filter
def escapenewline(value):
return value.replace('\n', '\"+')
Use a JSON encoder to create a valid string which you can use in your JavaScript code.
From a quick search Django doesn't seem to have a template filter for this but it shouldn't be too hard to add. Assuming your json filter is called tojson the code in the template would look like this:
$("#id_review").val({{ whatever|tojson }});
Here's how the filter could look like:
import json
#register.filter
def tojson(value):
return json.dumps(value)

Handlebars.js doesn't like square brackets in the front

I am using PHP-backend, Backbone.js and Handlebars.js. My javascript requests for data, and JSON data is returned successfully (json_encode).
When I give this JSON data to the handlebars template, it is not displaying. I realised the square brackets in front and at the back of my JSON object are 'disliked' by Handlebars.js and not being displayed. Take a look at the code below.
var ArticleListView = Backbone.View.extend(
{
el: $('#main'),
render: function()
{
var template = Handlebars.compile($("#articles_hb").html());
$(this.el).html(template([{"articles":[{"title" : "1"}, {"title" : "2"}]}]));
return this;
}
});
Now, if I take the brackets out, it works fine. What's going on? Why are the square brackets there in the first place? How do I get rid of them?
It's perfectly reasonable to call Handlebars to loop through the output of a collection.
Also an array is not a bad design decision for data handling in views.
Handlebars has a special syntax for dealing with numeric or symbol identifiers, as described here. So, the more correct answer is that Handlebars can access arrays in templates like this:
{{people.attributes.[0]}} // akin to people.attributes[0]
{{people.attributes.[1]}} // akin to people.attributes[1]
Input: mails:[{headers: {subject: ["Hello Darling", "...another"]}}, ...more ]
<ul>
{{#each mails}}
<li>.
{{headers.subject.[0]}}
</li>
{{/each}}
</ul>
Handlebars wants an object for the context as it uses the context as a simple lookup table for template values. So you need to pass an object ({ ... }) to template(), not an array ([ ... ]).
Someone is give you a one element array that contains the context object you need. Either fix the PHP that is producing the JSON to send a JSONified object (associative array in PHP terms) without the array wrapper or strip off the array in the client code with something like this:
$(this.el).html(template(context[0]));
If you have this literal code:
$(this.el).html(template([{"articles":[{"title" : "1"}, {"title" : "2"}]}]));
in your JavaScript file then you have to what is generating that code and fix it. If you do have literal data like that embedded in your Backbone view then you're probably not using Backbone correctly, the data for your template should probably be coming from a Backbone model.
If you're getting that JSON from a Backbone model then I'd guess that you're calling toJSON on a collection (which returns an array) rather than a single model where toJSON should give you a JavaScript object.

Categories

Resources