Reputation: 967
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.
Upvotes: 0
Views: 3205
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
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