Mike Resoli
Mike Resoli

Reputation: 967

Access specific dictionary key from within Flask Template

I'm setting up my personal website using Python and Flask. For the blog section, I am reading my blog posts from a json file and then displaying them via. a template. I'm am reading the file in python like so:

@app.route('/blog')
def renderblog():
    filename = os.path.join(app.static_folder, 'blogs.json')
    with open(filename) as blog_file:
        data = json.load(blog_file)

    return render_template("blog.html", posts=data['posts'])

The content of the json file is:

{
  "posts": {
    "1": {
      "title": "Welcome",
      "author": "mikeres0",
      "date": "",
      "tags": "welcome,intro,outline",
      "content": "<p>Test content</p>",
      "hidden": "0"
    },
    "2": {
      "title": "Welcome",
      "author": "mikeres0",
      "date": "",      
      "tags": "",
      "content": "<p>Test content</p>",
      "hidden": "1"
    }
  }
}

Within the template, I am displaying the content like:

{% if posts %}
  {% for key, value in posts.items() %}
      {% for blogKey, blogValue in value.items() %}   
        {% if blogKey == 'title' %}
          {{ blogValue }}
        {% endif %}
        {% if blogKey == 'content' %}
          {{ blogValue|safe }}
        {% endif %}
      {% endfor %}
  {% endfor %}
{% endif %}

The problem I'm having is that although the json is formatted how I'd like it to be, when the file is read into a dictionary it does not keep it's ordering. In this specific case, how can I access certain key, value pairs? Please find a screenshot below. screenshot

Upvotes: 0

Views: 3205

Answers (2)

Mike Resoli
Mike Resoli

Reputation: 967

I had a bit of fiddling around with @PJ Santoro's answer but I decided to go with another approach, by loading the json into an OrderedDict:

import collections

@app.route('/blog')
def renderblog():
    filename = os.path.join(app.static_folder, 'blogs.json')
    with open(filename) as blog_file:
        data = json.load(blog_file, object_pairs_hook=collections.OrderedDict)

    return render_template("blog.html", posts=data['posts'])

Upvotes: 0

abigperson
abigperson

Reputation: 5372

So, assuming, based on your example your dictionary "keys" are integer values stored as strings you could do this:

@app.route('/blog')
def renderblog():
    filename = os.path.join(app.static_folder, 'blogs.json')
    with open(filename) as blog_file:
        data = json.load(blog_file)

    order = [x for x in data['posts']]
    order.sort(key=lambda x: int(x))

    return render_template("blog.html", posts=data['posts'], order=order)

Then, within your Jinja2 template:

{% if posts %}
  {% for key in order %}
    {% for blogKey, blogValue in posts.key.items() %}   
      {% if blogKey == 'title' %}
        {{ blogValue }}
      {% endif %}
      {% if blogKey == 'content' %}
        {{ blogValue|safe }}
      {% endif %}
    {% endfor %}
  {% endfor %}
{% endif %}

In my opinion the best practice I use (please challenge me on this) is to use a list of dictionaries, instead of iterating through a dictionary, which is not ordered. So, a more ideal JSON structure would be like this:

{
  "posts": [
    {
      "order": 1
      "title": "Welcome",
      "author": "mikeres0",
      "date": "",
      "tags": "welcome,intro,outline",
      "content": "<p>Test content</p>",
      "hidden": "0"
    },
    {
      "order": 2
      "title": "Welcome",
      "author": "mikeres0",
      "date": "",      
      "tags": "",
      "content": "<p>Test content</p>",
      "hidden": "1"
    }
  ]
}

Which you could sort more simply like this:

from operator import attrgetter

data['posts'].sort(key=attrgetter('order'))

Upvotes: 2

Related Questions