DEV Community

How can I make a list of group data by month-year in rest Framework with json output?

Borhan Tipu on August 01, 2019

The json data format I want like this: [ { monthName: "AUG 2019", items: [ { day: "03", description: "Baseball", ...
Collapse
 
lord007tn profile image
Raed Bahri • • Edited

i have a solution that I've tried and worked for me.

models.py


class Item(models.Model):

    time = models.IntegerField()
    description = models.CharField(max_length=50)

class GroupData(models.Model):

    item = models.ForeignKey(Item, related_name='items', on_delete=models.CASCADE)

    date = models.DateField()

serilizer.py


import datetime
class GroupDataSerializer(serializers.ModelSerializer):

    date = serializers.SerializerMethodField(method_name='get_date')
    class Meta:
        model = GroupData
        fields =('__all__')

    def get_date(self, instance):
        date = datetime.datetime.now()
        return date.strftime("%m/%d/%Y")

views.py


class GroupDataView(generics.ListAPIView):

    queryset = GroupData.objects.all()
    serializer_class = GroupDataSerializer
    
    def get_queryset(self):
        queryset = self.queryset

        return queryset.objects.filter(data=id).order_by('-date')

hope it works for you. DM me if you have a problem

Collapse
 
tipu profile image
Borhan Tipu •

My Model Is

class Event(models.Model):
title = models.CharField(max_length=255, default=None, unique=True)
description = models.TextField()
date = models.DateField(default=None, null=True)

I want to group the from the date field with month-year( like 01-2017 or JAN-2017)

I see that you created another model for that. Can I do it with single model?

Collapse
 
lord007tn profile image
Raed Bahri •

yeah you can but as a best practice if you have a data that require more than one field just put it in a class and refer to it as a foreign key

so it will be a class for your event that have date and name
and a class for group of event or category that take events as foreign keys
in django admin you can control that easily

Thread Thread
 
tipu profile image
Borhan Tipu •

Ok. Let me try this. If it is worked that would be great

Collapse
 
tipu profile image
Borhan Tipu •

Here are my codes

models.py

class Event(models.Model):
    title = models.CharField(max_length=255, default=None, unique=True)
    link = models.URLField(default=None, null=True)
    description = models.TextField()

    def __str__(self):
        return self.title

    class Meta:
        db_table = 'events'

class EventGroup(models.Model):
    event = models.ForeignKey(Event, related_name='events', on_delete=models.CASCADE)
    event_date = models.DateField()

    class Meta:
        db_table = 'event_group'

views.py

class EventGroupData(ListAPIView):
    queryset = EventGroup.objects.all()
    serializer_class = EventGroupSerializer

    def get_queryset(self):
        queryset = self.queryset

        return queryset.objects.filter(data=id).order_by('-event_date')

Serializer.py

import datetime
class EventGroupSerializer(serializers.ModelSerializer):
    event_date = serializers.SerializerMethodField(method_name='get_date')
    class Meta:
        model = EventGroup
        fields = '__all__'

    def get_date(self, instance):
        event_date = datetime.datetime.now()
        return event_date.strftime("%m/%d/%Y")
Collapse
 
tipu profile image
Borhan Tipu •

can you please tell me why same month showing twice with same data?
models.py

class Event(models.Model):
    title = models.CharField(max_length=255, default=None, unique=True)
    link = models.URLField(default=None, null=True)
    description = models.TextField()
    date = models.DateField(default=None, null=True)
    is_published = models.BooleanField(default=False)
    created = models.DateTimeField(auto_now_add=True)
    updated = models.DateTimeField(auto_now=True)

    def __str__(self):
        return self.title

    class Meta:
        db_table = 'events'
        verbose_name = 'event'
        verbose_name_plural = 'events'

class EventGroup(models.Model):
    event = models.ForeignKey(Event, related_name='events', on_delete=models.CASCADE)
    date = models.DateField()
    created = models.DateTimeField(auto_now_add=True)
    updated = models.DateTimeField(auto_now=True)
    class Meta:
        db_table = 'event_group'

serializer.py

class EventGroupSerializer(serializers.ModelSerializer):
    events = serializers.SerializerMethodField(method_name='get_events')
    month_year = serializers.SerializerMethodField(method_name='get_month_year')

    total = serializers.SerializerMethodField(method_name='get_count_events')
    class Meta:
        model = EventGroup
        fields = ('month_year', 'total', 'events',)

    def get_count_events(self, instance):
        org_date = str(instance['date'])
        date = datetime.datetime.strptime(org_date, "%Y-%m-%d")
        month = date.month
        year = date.year
        count = Event.objects.filter(date__month=month, date__year=year).count()
        return count

    def get_month_year(self, instance):
        org_date = str(instance['date'])
        date = datetime.datetime.strptime(org_date, "%Y-%m-%d").date()
        month_year = str(date.month)+'-'+str(date.year)
        return str(month_year)

    def get_events(self, instance):
        org_date = str(instance['date'])
        date = datetime.datetime.strptime(org_date, "%Y-%m-%d")
        month = date.month
        year = date.year
        events = Event.objects.filter(date__month=month, date__year=year)
        event_serializer = EventSerializer(events, many=True)
        return event_serializer.data

views.py

class EventGroupData(ListAPIView):
    queryset = EventGroup.objects.all()

    serializer_class = EventGroupSerializer


    def get_queryset(self):
        queryset = self.queryset

        return queryset.annotate(month=TruncMonth('date')).values('date').annotate(c=Count('id')).order_by()

results

{
    "count": 4,
    "next": null,
    "previous": null,
    "results": [
        {
            "month_year": "6-2019",
            "events": [
                {
                    "id": 30,
                    "title": "Event 2",
                    "description": "Event 2",
                    "date": "2019-06-02"
                },
                {
                    "id": 31,
                    "title": "Event 3",
                    "description": "Event 3",
                    "date": "2019-06-04"
                }
            ]
        },
        {
            "month_year": "6-2019",
            "events": [
                {
                    "id": 30,
                    "title": "Event 2",
                    "description": "Event 2",
                    "date": "2019-06-02"
                },
                {
                    "id": 31,
                    "title": "Event 3",
                    "description": "Event 3",
                    "date": "2019-06-04"
                }
            ]
        },
        {
            "month_year": "9-2019",
            "events": [
                {
                    "id": 32,
                    "title": "Event 4",
                    "description": "Event 4",
                    "date": "2019-09-04"
                },
                {
                    "id": 29,
                    "title": "Event 1",
                    "description": "Event 1",
                    "date": "2019-09-25"
                }
            ]
        },
        {
            "month_year": "9-2019",
            "events": [
                {
                    "id": 32,
                    "title": "Event 4",
                    "description": "Event 4",
                    "date": "2019-09-04"
                },
                {
                    "id": 29,
                    "title": "Event 1",
                    "description": "Event 1",
                    "date": "2019-09-25"
                }
            ]
        }
    ]
}

it should be like this

{
    "count": 4,
    "next": null,
    "previous": null,
    "results": [
        {
            "month_year": "6-2019",
            "events": [
                {
                    "id": 30,
                    "title": "Event 2",
                    "description": "Event 2",
                    "date": "2019-06-02"
                },
                {
                    "id": 31,
                    "title": "Event 3",
                    "description": "Event 3",
                    "date": "2019-06-04"
                }
            ]
        },
        {
            "month_year": "9-2019",
            "events": [
                {
                    "id": 32,
                    "title": "Event 4",
                    "description": "Event 4",
                    "date": "2019-09-04"
                },
                {
                    "id": 29,
                    "title": "Event 1",
                    "description": "Event 1",
                    "date": "2019-09-25"
                }
            ]
        },

    ]
}