I'm trying to create an archive list with counts using SQLAlchemy, Flask and Jinja that looks like this. I don't want to show months that don't have posts. I can't figure out how to get the unique years, months and counts for each in a dictionary.
2012 (11)
- January (3)
- February (5)
- April (3)
2013 (14)
- April (2)
- May (8)
- June (2)
- December
2014 (13)
- January (3)
- February (8)
- March (2)
model
class Post(db.Model):
''' Returns the Post table.
'''
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(80))
url = db.Column(db.String(120), unique=True)
body = db.Column(db.Text)
create_date = db.Column(db.DateTime)
pub_date = db.Column(db.DateTime)
pub_status = db.Column(db.Text(80))
author_id = db.Column(db.Integer, db.ForeignKey('user.id'))
topic_id = db.Column(db.Integer, db.ForeignKey('topic.id'))
# relationships
# one-to-many
author = db.relationship('User', backref=db.backref('post', lazy='dynamic'))
topic = db.relationship('Topic', backref=db.backref('post', lazy='dynamic'))
# many-to-many
tags = db.relationship('Tag', secondary=posts_tags, backref='posts', lazy='dynamic')
UPDATE
This code creates the dictionary, but not sure how I would add the counts. Any ideas? Is there a better approach?
views
# custom filter converts month number to "January", etc.
@app.template_filter('month_number')
def month_name(month_number):
return calendar.month_name[month_number]
@app.route('/archive')
def display_archive():
p = db.session.query(Post.pub_date).all()
d = defaultdict(set) # removes the duplicate months by putting into sets.
n = {}
for i in p:
d[i.pub_date.year].add(i.pub_date.month)
d.items()
# first part returns eliminates dup months by making sets, needs sorting.
# defaultdict(<type 'set'>, {2012: set([1, 2, 4]),\
# 2013: set([4, 12, 5, 6]), 2014: set([1, 2, 3])})
for key, value in d.iteritems() :
a = value
a = list(a) #convert sets to list.
a.sort() # soft the list.
n[key] = a
return render_template('archive.html', d=d, n=n)
# convert to list for easy sorting.
#{2012: [1, 2, 4], 2013: [4, 5, 6, 12], 2014: [1, 2, 3]}
jinja2 template
<dl>
{% for key, value in n.iteritems() %}
<dt>{{ key }}</dt>
{% for v in value %}
<dd><a href="/{{ key }}/{{ v }}">{{ v|month_number }}</a></dd>
{% endfor %}
{% endfor %}
</dl>
Again, it works... but not sure how to add the counts. It will have to be done before the defaultdict function I assume.