仅按日期范围选择相关模型,并序列化为嵌套列表

时间:2018-06-18 23:45:09

标签: django django-rest-framework

如果我的模型看起来像这样:

class ImageUpload(models.Model):
    created = models.DateTimeField(default=timezone.now)
    iot_device = models.ForeignKey(IotDevice, related_name = 'uploads')
    datafile = models.ImageField(upload_to = upload_path_handler)

class IotDevice(models.Model):
    device_name = models.CharField(max_length=100, default='device1')

class Batch(models.Model):
    begindate = models.DateTimeField(auto_now_add = False, blank = True, null = True)
    enddate = models.DateTimeField(auto_now_add = False, blank = True, null = True)
    iot_device = models.ForeignKey(IotDevice, related_name = 'batch_iotdevice')

我想选择批量处于活动状态的所有ImageUpload(只有一个begindate,enddate需要为NULL)。

我在视图中写了以下代码:

active_batch = ImageUpload.objects.filter(iot_device__batch_iotdevice__enddate__isnull = True, iot_device__batch_iotdevice__begindate__lte = F('created')).select_related('iot_device')

在执行active_batch.query时会生成几乎正确的SQL查询,但它不包含api_batch字段。

SELECT
  "api_imageupload"."id",
  "api_imageupload"."created",
  "api_imageupload"."iot_device_id",
  "api_imageupload"."datafile",
  "api_iotdevice"."id",
  "api_iotdevice"."device_name"
FROM "api_imageupload"
INNER JOIN "api_iotdevice"
    ON ("api_imageupload"."iot_device_id" = "api_iotdevice"."id")
INNER JOIN "api_batch"
    ON ("api_iotdevice"."id" = "api_batch"."iot_device_id")
WHERE ("api_batch"."enddate" IS NULL AND "api_batch"."begindate" <= ("api_imageupload"."created"))
ORDER BY "api_imageupload"."created" DESC

Q1:如何修改我的过滤器查询以返回以下序列化表示。

Q2:我如何编写序列化程序,以便将Batch和其下的每个ImageUpload作为子项,e.x。:

[
{
    "begindate": "2018-03-01T12:00:07.501686",
    "enddate": "NULL"
    "device_name": "CONTAINER_1",
    "uploads": [
        {
            "created": "2018-06-18T12:00:07.501686",
            "datafile": "/media/cam/CONTAINER_1/20180618_120007.jpg",
            "thumbnail_path": "/media/cache/80/d3/80d34e2e28773d2c2e11548525e9fd19.jpg"
        },
        {
            "created": "2018-06-18T00:00:05.017622",
            "datafile": "/media/cam/CONTAINER_1/20180618_000005.jpg",
            "thumbnail_path": "/media/cache/b7/f8/b7f836e52b975a61558ae62d0a6132a6.jpg"
        },
    ]
},
    {
    "begindate": "2018-06-01T12:00:07.501686",
    "enddate": "NULL"
    "device_name": "CONTAINER_2",
    "uploads": [
        {
            "created": "2018-06-18T12:00:07.501686",
            "datafile": "/media/cam/CONTAINER_2/20180622_120007.jpg",
            "thumbnail_path": "/media/cache/80/d3/80d34e2e287353532e11548525e9fd19.jpg"
        },
    ]
}
]

由于

1 个答案:

答案 0 :(得分:1)

serializers.py

class ImageUploadSerializer(ModelSerializer):
    thumbnail_path = serializers.SerializerMethodField()

    def get_thumbnail_path(self, instance):
        return ''

    class Meta:
        model = ImageUpload
        fields = ('id', 'created', 'datafile', 'thumbnail_path')

class BatchSerializer(ModelSerializer):
    iot_device = serializers.StringRelatedField()
    uploads = serializers.SerializerMethodField()

    def get_uploads(self, instance):
        queryset = ImageUpload.object.filter(iot_device=instance.iot_device, created__gte=instance.begindate, created__lte=instance.enddate)
        return ImageUploadSerializer(queryset, many=True).data

    class Meta:
        model = Batch
        fields = ('id', 'begindate', 'iot_device', 'uploads')

views.py:

class BatchViewSet(ModelViewSet):
    queryset = Batch.objects.all()
    serializer_class = BatchSerializer
    permission_classes = (IsAuthenticated,)

    def list(self, request, *args, **kwargs):
        queryset = self.filter_queryset(self.get_queryset())
        serializer = BatchSerializer(queryset, context=self.get_serializer_context(), many=True)
        return Response(serializer.data)