DRF-сериализатор для группировки данных по атрибутам в массивы - PullRequest
0 голосов
/ 22 сентября 2019

Я хотел бы создать сериализатор Django Rest Framework, который может группировать мои данные на основе атрибутов каждого объекта.

Мои модели описываются следующим образом:

class Courses(models.Model):
    coursenum = models.AutoField(db_column='courseNum', primary_key=True)
    coursecode = models.CharField(db_column='courseCode', max_length=10, blank=True, null=False)

    class Meta:
        managed = False
        db_table = 'courses'


class Sections(models.Model):
    sectionnum = models.AutoField(db_column='sectionNum', primary_key=True)
    semester = models.CharField(max_length=1, blank=True, null=False)
    section = models.CharField(max_length=2, blank=True, null=False)

    class Meta:
        managed = False
        db_table = 'sections'

class Teachers(models.Model):
    teachernum = models.AutoField(db_column='teacherNum', primary_key=True)
    teachername = models.CharField(max_length=60, blank=True, null=False)

    class Meta:
        managed = False
        db_table = 'teachers'


class Timeslots(models.Model):
    timeslotnum = models.AutoField(db_column='timeSlotNum', primary_key=True)
    starttime = models.TimeField(db_column='startTime', blank=True, null=False)
    endtime = models.TimeField(db_column='endTime', blank=True, null=False)

    class Meta:
        managed = False
        db_table = 'timeslots'


class Venues(models.Model):
    venuenum = models.AutoField(db_column='venueNum', primary_key=True)
    venuename = models.CharField(db_column='venueName', max_length=6, blank=False, null=False)

    class Meta:
        managed = False
        db_table = 'venues'


class Slots(models.Model):
    daynum = models.IntegerField(db_column='dayNum', primary_key=True)
    venuenum = models.ForeignKey(Venues, models.CASCADE, db_column='venueNum')
    timeslot = models.ForeignKey(Timeslots, models.CASCADE, db_column='timeSlot')
    coursenum = models.ForeignKey(Courses, models.CASCADE, db_column='courseNum', blank=True, null=True)
    teachernum = models.ForeignKey(Teachers, models.CASCADE, db_column='teacherNum', blank=True, null=True)
    sectionnum = models.ForeignKey(Sections, models.CASCADE, db_column='sectionNum', blank=True, null=True)

    class Meta:
        managed = False
        db_table = 'slots'
        unique_together = (('daynum', 'venuenum', 'timeslot'),)

Использование простогоСериализатор модели с вложенными вызовами сериализатора родного брата, я могу получить данные следующим образом:

"slots": [
        {
            "daynum": 1,
            "venue": {
                "venuenum": 2,
                "venuename": "FF-105"
            },
            "timeslot": {
                "timeslotnum": 2,
                "starttime": "09:30:00",
                "endtime": "10:20:00"
            },
            "course": null,
            "teacher": null,
            "section": null
        },
        {
            "daynum": 1,
            "venue": {
                "venuenum": 2,
                "venuename": "FF-105"
            },
            "timeslot": {
                "timeslotnum": 3,
                "starttime": "10:30:00",
                "endtime": "11:20:00"
            },
            "course": {
                "coursenum": 1,
                "coursecode": "CS 2002"
            },
            "teacher": {
                "teachernum": 1,
                "teachername": "TEHNIAT MIRZA"
            },
            "section": {
                "sectionnum": 1,
                "semester": "3",
                "section": "B"
            }
        },
]

Однако я хочу перебрать эти результаты в таблице React и хочу отсортировать их и сгруппировать их по каждому объекту.атрибут, так что его легко показать:

Желаемый вывод

"slots": [
    '1': //the day number
        [
            'FF-104': []
            'FF-105': [
                    {
                        "daynum": 1,
                        "venue": {
                            "venuenum": 2,
                            "venuename": "FF-105"
                        },
                        "timeslot": {
                            "timeslotnum": 2,
                            "starttime": "09:30:00",
                            "endtime": "10:20:00"
                        },
                        "course": null,
                        "teacher": null,
                        "section": null
                    },
                    {
                        "daynum": 1,
                        "venue": {
                            "venuenum": 2,
                            "venuename": "FF-105"
                        },
                        "timeslot": {
                            "timeslotnum": 3,
                            "starttime": "10:30:00",
                            "endtime": "11:20:00"
                        },
                        "course": {
                            "coursenum": 1,
                            "coursecode": "CS 2002"
                        },
                        "teacher": {
                            "teachernum": 1,
                            "teachername": "TEHNIAT MIRZA"
                        },
                        "section": {
                            "sectionnum": 1,
                            "semester": "3",
                            "section": "B"
                        }
                    },
            ]
        ]
]1

Подводя итог, я хочу сделать это
На первом уровне сгруппируйте результаты по атрибуту daynum
На втором уровне сгруппируйте результаты по названию (или нумерации, которые работают), а также сортируйте по временным интервалам.

1 Ответ

0 голосов
/ 25 сентября 2019

Итак, из моих выводов, сериализаторы Django Rest Framework не работают таким образом, и, как указал @Andrew Backer, мне, возможно, придется использовать специальный запрос для извлечения данных соответствующим образом.

Изначально я изучалitertools.groupby но для меня это было не так интуитивно понятно, поэтому я решил написать собственный запрос.

Как работал запрос:

Получить все объекты Slot, но упорядочить их следующим образом: Slots.objects.all().order_by('daynum','venuenum__venuename','timeslot')

Использование вложенного collections.defaultdict, то есть: data = defaultdict(lambda: defaultdict(list)) Для каждого daynum, добавьте список для venuenum__venuename и добавьте объекты Slot соответственно

Код:

class TimetableGenerateView(APIView):
    def get(self, request):
        data = defaultdict(lambda: defaultdict(list))
        slots = Slots.objects.all().order_by('daynum','venuenum__venuename','timeslot')
        for slot in slots:
            data[slot.daynum][slot.venuenum.venuename].append(SlotSerializer(slot).data)
        return Response(data)
...