我想创建一个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属性分组
在第二层上,将结果按场所名称(或可用的数字)分组,同时按时隙排序。
答案 0 :(得分:0)
因此,从我的发现来看,Django Rest Framework序列化器无法正常工作,正如@Andrew Backer指出的那样,我可能必须使用自定义查询来相应地检索数据。
我本来是研究itertools.groupby
的,但对我而言却不那么直观,因此我只写了一个自定义查询。
查询的工作方式:
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)