Django Year/Month based posts archive

2024/9/23 12:32:29

i'm new to Django and started an application, i did the models, views, templates, but i want to add some kind of archive to the bottom of the page, something like this http://www.flickr.com/photos/ionutgabriel/3990015411/.

So i want to list all years and next to them all the months from that year. The months who have posts to be links and other no. Also i want to translate the months names cause i need them in romanian.

What i've done so far is:

in my view:

def archive(request): arch = Post.objects.dates('date', 'month', order='DESC') archives = {} for i in arch: tp = i.timetuple() year = tp[0] month = tp[1] if year not in archives: archives[year] = [] archives[year].append(month) else: if month not in archives[year]: archives[year].append(month) return render_to_response('blog/arhiva.html', {'archives':archives}) 

and in my template:

    {% for years, months in archives.items %} {{ years }} {% for month in months %} <a href="{{ years }}/{{ month }}">{{ month }}</a> {% endfor %} <br /> {% endfor %} 

this returns something like:

       2008               10 2009               10               9 2007               10 

but i can't sort them at all...by year or by anything, and also i don't know how to add all months(the names), i want them like this:

   2009 Ian Feb Mar Apr Mai Iun Iul Aug Sept Oct Noi Dec       2008 Ian Feb Mar Apr Mai Iun Iul Aug Sept Oct Noi Dec2007 Ian Feb Mar Apr Mai Iun Iul Aug Sept Oct Noi Dec

with link on the months who have entries.

Thank you for your help!

p.s. sorry for my English

LE: Maybe i put the question in a wrong way, i know how to obtain dates, but i don't know how to format them to look like these:

   2009 Ian Feb Mar Apr Mai Iun Iul Aug Sept Oct Noi Dec       2008 Ian Feb Mar Apr Mai Iun Iul Aug Sept Oct Noi Dec2007 Ian Feb Mar Apr Mai Iun Iul Aug Sept Oct Noi Dec

all i can get from arch = Post.objects.dates('date', 'month', order='DESC')

with

{{ archives }} in template is something like:

[datetime.datetime(2009, 10, 1, 0, 0), datetime.datetime(2009, 9, 1, 0, 0),datetime.datetime(2008, 10, 1, 0, 0), datetime.datetime(2007, 10, 1, 0, 0)]

then i've tried a loop:

{% for archive in archives %}{{ archive }} <br />{% endfor %}

and got:

2009-10-01 00:00:00 
2009-09-01 00:00:00 
2008-10-01 00:00:00 
2007-10-01 00:00:00 

After that tried something like this:

{% for archive in archives %}{{ archive|date:"Y: m" }} <br />{% endfor %}

and got:

2009: 10 
2009: 09 
2008: 10 
2007: 10 

Here i'm stuck and don't know how to format the data so i can get distinct years with all the months and only the months who have entries to be links...

Any ideas?

Thank you in advance!

Answer

Firstly, the datetime format strings are given in the django docs. I think you want capital instead of lowercase 'M'.

Since you want to display all 12 months of a year, even if only some have posts, we'll create an archives object to pass to the template. I've chosen to use a dictionary where

  • the keys are the years
  • the values are a list of 12 [datetime, bool] pairs, where datetime represents a month, and bool is True if there are posts for that month.

Here's how we build the archives object in the view.

from datetime import datedef archive(request):arch = Post.objects.dates('date', 'month', order='DESC')archives = {}for i in arch:year = i.yearmonth = i.monthtry:archives[year][month-1][1]=Trueexcept KeyError:# catch the KeyError, and set up list for that yeararchives[year]=[[date(y,m,1),False] for m in xrange(1,13)]archives[year][month-1][1]=Truereturn render_to_response('blog/arhiva.html', {'archives':sorted(archives.items(),reverse=True)})

In the template, we loop through the months for each year, and display the link if appropriate.

{% for year, month_list in archives %}{{ year }} archives: {% for month, has_link in month_list %}{% if has_link %}<a href="/{{ month.year }}/{{ month.month }}/">{% endif %}{{ month|date:"M" }}{% if has_link %}</a>{% endif %}{% endfor %}
{% endfor %}

I haven't checked all the code so there might be a couple of bugs. It would be better to use the url template tag for the link, instead of hardcoding the url format. I have a feeling my answer might be overly complicated, but I've spent a while typing it up, so I may as well share it with the world.


Internationalization

I haven't used the internationalization features of Django, so I can't really help with the translation. I recommend you have a look at the documentation, and ask another question if there's a particular bit you don't understand.

Having said that, if you want to display the months is Romanian only, here's an ugly way to do it.

First, add the following line to the top of your archive function in the view.

rom_months = ['Ian', 'Feb', 'Mar', 'Apr', 'Mai', 'Iun', 'Iul', 'Aug', 'Sept', 'Oct', 'Noi', 'Dec']

Then substitute the following line into your view

archives[year]=[[date(y,k+1,1),False,rom] for k, rom in enumerate(rom_months)]

Finally substitute the following into the template

...
{% for month, has_link, rom_month in month_list %}{% if has_link %}<a href="/{{ month.year }}/{{ month.month }}/">{% endif %}{{ rom_month }}
...
https://en.xdnf.cn/q/71826.html

Related Q&A

ValueError: You are trying to load a weight file containing 6 layers into a model with 0

I have a simple keras model. After the model is saved. I am unable to load the model. This is the error I get after instantiating the model and trying to load weights:Using TensorFlow backend. Tracebac…

cProfile with imports

Im currently in the process of learn how to use cProfile and I have a few doubts.Im currently trying to profile the following script:import timedef fast():print("Fast!")def slow():time.sleep(…

Python AWS Lambda 301 redirect

I have a lambda handler written in Python and I wish to perform a 301 redirect to the browser. I have no idea how I can configure the response Location header (or the status code) -- the documentation …

Google Authenticator code does not match server generated code

BackgroundIm currently working on a two-factor authentication system where user are able to authenticate using their smartphone. Before the user can make use of their device they need to verify it firs…

Gekko Non-Linear optimization, object type error in constraint function evaluating if statement

Im trying to solve a non-linear optimization problem. Ive duplicated my issue by creating the code below. Python returns TypeError: object of type int has no len(). How can I include an IF statement in…

Store large dictionary to file in Python

I have a dictionary with many entries and a huge vector as values. These vectors can be 60.000 dimensions large and I have about 60.000 entries in the dictionary. To save time, I want to store this aft…

Python: override __str__ in an exception instance

Im trying to override the printed output from an Exception subclass in Python after the exception has been raised and Im having no luck getting my override to actually be called.def str_override(self):…

How hide/show a field upon selection of a radio button in django admin?

models.pyfrom django.db import models from django.contrib.auth.models import UserSTATUS_CHOICES = ((1, Accepted),(0, Rejected),) class Leave(models.Model):----------------status = models.IntegerField(c…

format/round numerical legend label in GeoPandas

Im looking for a way to format/round the numerical legend labels in those maps produced by .plot() function in GeoPandas. For example:gdf.plot(column=pop2010, scheme=QUANTILES, k=4)This gives me a lege…

Python pickle crash when trying to return default value in __getattr__

I have a dictionary like class that I use to store some values as attributes. I recently added some logic(__getattr__) to return None if an attribute doesnt exist. As soon as I did this pickle crashe…