DRF序列化器可按属性将数据分组到数组中

时间:2019-09-22 18:32:22

标签: python json django django-rest-framework serializer

我想创建一个Django Rest Framework序列化程序,该序列化程序可以根据每个对象的属性对数据进行分组。

我的模型描述如下:

Future<void> dbConfig() async {
  var io = new Server();
  var nsp = await io.of('/some');
  nsp.on('connection', (Socket client) {
    print('connection /some');
    client.on('message', (data) {
      print('data from /some => $data');
      client.emit('fromServer', "ok 2");
    });
  });
  io.on('connection', (Socket client) {
    print('connection default namespace');
    client.on('message', (data) {
      print('data from default => $data');
      client.emit('fromServer', "ok");
    });
  });
  io.listen(4000);

  // Dart client
  IO.Socket socket = await IO.io('http://localhost:4000');
  socket.on('connect', (_) {
    print('connect');
    socket.emit('message', 'test');
  });
  socket.on('event', (data) => print(data));
  socket.on('disconnect', (_) => print('disconnect'));
  socket.on('fromServer', (_) => print(_));
}

使用带有嵌套兄弟同级序列化程序调用的简单模型序列化程序,我可以获得以下数据:

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'),)

但是,我想在React表中遍历这些结果,并希望对它们进行排序并根据每个对象的属性对其进行分组,以便于显示:

所需的输出

"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"
            }
        },
]

总而言之,我想做的是
在第一级,将结果按daynum属性分组
在第二层上,将结果按场所名称(或可用的数字)分组,同时按时隙排序。

1 个答案:

答案 0 :(得分:0)

因此,从我的发现来看,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)