Phrixus
Phrixus

Reputation: 1219

Parse JSON object to Django template

I am trying to parse a JSON object to Django template so that I can parse this json object to javascript.

Here how my view creates and parse the json object to the template:

    countries = Country.objects.filter(Enabled=True)
    citiesByCountry = {}

    for country in countries:
        citiesInCountry = City.objects.filter(Enabled=True, Country=country)
        cities = []

        for city in citiesInCountry:
            cities.append(city.Name)

        citiesByCountry[country.Name] = cities

    context = {'citiesByCountry': json.dumps(citiesByCountry)}
    return render(request, 'index.html', context)

Now I would like to retrieve all the keys (which will be countries) to my template this way:

{% for country in citiesByCountry%}
   <option>{{ country }}</option>
{% endfor %}

But what I get is an option for each character in strings instead of the country name as a whole.

I tried to use .item1 but this didn't work either.

I don't show JavaScript code in my example above as the intent of the question is how to parse and retrieve strings from a JSON object. I need to process this data using javascript later. In specific once the user change country I would like to populate another dropdown that will handle the cities, and therefore I thought to use JSON and Javascript to achieve that, as I don't want to refresh the page on each change.

Any help?

Upvotes: 2

Views: 11536

Answers (3)

frnhr
frnhr

Reputation: 12903

To answer you question in the title:

In <head> (or somewhere), build your array of counties:

<script>
    var country_objs = [];
    {% for country in citiesByCountry%}
        country_objs.push({{country|escapejs}});
    {% endfor %}
<\script>

Docs for the filter: https://docs.djangoproject.com/en/1.9/ref/templates/builtins/#escapejs

Then you can use it in JavaScript (but not in Django template). For example:

<select id="cities"><\select>
<script>
    var $cities_select = $("#cities");
    $(country_objs).each(function(){
        $cities_select.append('<option value="' + this.id_or_something + '">' + this.name + '<\option>');
    });
<\script>

But from your example I don't see why you need to encode it in JSON in the first place. Why not just pass a dict into the template (via context, just as everything else)?

P.S. Sorry for using jQuery, l'm just lazy :)

Upvotes: 4

Antoine Pinsard
Antoine Pinsard

Reputation: 34922

When you do citiesByCountry = json.dumps({'a': "b", 'c': None}), citiesByCountry is a string. This is why you get character after character when you iterate over it.

This string representing a JSON object, you can "affect" as-is to a JavaScript variable:

var citiesByCountry = {{ citiesByCountry }};

Which will output something like:

var citiesByCountry = {"a": "c", "d": null};

However, considering what you want to achieve:

In specific once the user change country I would like to populate another dropdown that will handle the cities

I highly recommend you to checkout django-autocomplete-light, which in addition to providing auto-completion, provides a way to filter results based on other fields. This will save you much efforts.

Upvotes: 1

Jacob Windsor
Jacob Windsor

Reputation: 6980

I think you have two options:

  1. Parse the JSON in the <option> tags with javascript.

    <script>
        var json = JSON.parse({{citiesByCountry}});
        //Loop through json and append to <option>
    </script>
    
  2. Add an extra context that isn't JSON serialized. This is a little redundant but a bit simpler.

    context = {'citiesByCountry_json': json.dumps(citiesByCountry), 'citiesByCountry': citiesbyCountry}
    

To be honest, I'd go for the second option since I don't see why you need to send it to the template in JSON in the first place.

Upvotes: 1

Related Questions