[Answered ]-Django: Group dates by Year

1👍

You used key:pair inside a list structure, so I will just assume its wrong and you meant a dictionary.

For that output, one possible solution:

serializers.py

class TimeLineSerializer(serializers.Serializer):

    timeline = serializers.SerializerMethodField()

    def get_timeline(self, obj):
        data = {}
        dates = obj.values('created__year').distinct()
        for date in dates:
            data[date['created__year']] = obj.filter(created__year=date['created__year']).values_list('created', flat=True)

        return data

views.py:

class TimeLineListAPIView(APIView):
    def get(self, request):
        qs = ProductModel.objects.all()
        serializer = TimeLineSerializer(qs)
        return Response(serializer.data)

output:

{
    "timeline": {
        "2021": [
            "2021-12-20",
            "2021-12-21",
            "2021-12-22"
        ],
        "2022": [
            "2022-12-20",
            "2022-12-21",
            "2022-12-23"
        ]
    }
}

Of course, there is possibly a cleaner solution that I don’t know of.

👤Niko

0👍

I don’t know if it’s the best solution but i’ve created a generic get_timeline function that goes like this ( thanks to @Niko for the inspiration):

def get_timeline(model_queryset, lookup_field):
    '''
    get timeline function will return a dictionary of dates grouping by years.
    '''
    timeline = {}
    for item in model_queryset:
        if hasattr(item, lookup_field):
            date = getattr(item, lookup_field)
            filters = { f'{ lookup_field }__year': date.year }
            timeline[date.year] = model_queryset.filter(**filters).values_list(lookup_field, flat=True)
        else:
            raise ValidationError(f'Object "{ item }" does not have "{ lookup_field }" attribute')
    return timeline

In views.py:

queryset =  ProductModel.objects.order_by('-created')
timeline = get_timeline(queryset, 'created')

And the output:

"timeline": {
    "2021": [
        "2021-12-1",
        "2021-11-1",
        "2021-10-1",
    ],
    "2022": [
        "2022-03-1",
        "2022-02-1",
        "2022-01-1",
    ],
},

This function will be call in the views.py file passing ProductModel objects as "model_queryset" and "created" as "lookup_field".

Hope that is a clean solution.

Leave a comment