如何在Django 1.11中使用查询集TruncYear产生的对象关系序列化列表

问题描述 投票:0回答:1

我设法从跟踪表中使用TruncYear / TruncMonth / TruncDay /等获取时间序列数据,如下所示。但是,该场所的数据仅会产生“ unity_id”。我希望将其序列化,以便它从关系Venue表中返回“名称”。

我正在使用Django 1.11和postgres 9.4

这是我的时间序列代码:

tracking_in_timeseries_data = Tracking.objects.annotate(
                                          year=TruncYear('created_at')).values('year', 'venue_id').annotate(
                                            count=Count('employee_id',
                                                        distinct = True)).order_by('year')   


return Response(tracking_in_timeseries_data, status=status.HTTP_200_OK)    

当前它输出如下:

[
    {
      "venue_id": 4,
      "year": "2017-01-01T00:00:00Z",
      "count": 1
    },
    {
      "venue_id": 2,
      "year": "2018-01-01T00:00:00Z",
      "count": 2
    },
    {
      "venue_id": 6,
      "year": "2019-01-01T00:00:00Z",
      "count": 1
    }
  ]

我想爆炸会场数据以返回ID和名称,如下所示:

  [
    {
      "venue": {
                id: 4,
                name: "room A"
                },
      "year": "2017-01-01T00:00:00Z",
      "count": 1
    },
    {
      "venue": {
                id: 2,
                name: "room B"
                },
      "year": "2018-01-01T00:00:00Z",
      "count": 2
    },
    {
      "venue": {
                id: 6,
                name: "room C"
                },
      "year": "2019-01-01T00:00:00Z",
      "count": 1
    }
  ]

如何爆炸“场地”以返回ID和名称?该名称可用于演示。

更新(这是一些失败的尝试):

仅显示计数,但累积(https://gist.github.com/axilaris/0cd86cec0edf675d654eadb3aff5b066)。有点奇怪,不确定为什么。

class TimeseriesSerializer(serializers.ModelSerializer):

    venue = VenueNameSerializer(source="venue_id",many=False, read_only=True)
    year = serializers.TimeField(read_only=True)
    count = serializers.IntegerField(read_only=True)

    class Meta:
        model = Tracking
        fields = ("venue",
                  "year",
                  "count")


class TimeseriesSerializer(serializers.Serializer): <-- here is another try but doesnt work serializers.Serializer

    venue_id = VenueNameSerializer(many=False, read_only=True)
    year = serializers.TimeField(read_only=True)
    count = serializers.IntegerField(read_only=True)

我认为答案非常接近:django rest framework serialize a dictionary without create a model

仅供参考,这是我的实际代码(必须在此处输入),名称可能略有不同,但整体意图是相同的。 https://gist.github.com/axilaris/919d1a20d3e799101a8cf6aeb4d120b5

django postgresql serialization time-series django-1.11
1个回答
0
投票

您需要为会场创建一个序列化器,该序列化器显示idname字段并将其用作TrackingSerializer中的字段。

在您的情况下,还需要考虑其他事项:由于您正在使用values进行分组,因此从查询集中获得的内容不是Tracking对象,因此无法将venue_id转换为Venue ] DRF对象。

要解决此问题,您需要重写to_representationVenueSerializer方法以从其主键获取Venue对象。

我提供了模型和视图,为您提供了一个有效的示例,但是您可能只需要序列化器和视图中经过调整的查询集。

型号

class Employee(models.Model):
    first_name = models.CharField(max_length=128)
    last_name = models.CharField(max_length=128)


class Venue(models.Model):
    name = models.CharField(max_length=128)


class Tracking(models.Model):
    venue = models.ForeignKey(Venue)
    employee = models.ForeignKey(Employee)
    created_at = models.DateTimeField(auto_now_add=True)

视图

class TrackingViewSet(viewsets.ModelViewSet):
    queryset = (
        Tracking.objects
        .annotate(
            year=ExtractYear('created_at'),
        )
        .values('year', 'venue')
        .annotate(
            count=Count('employee_id', distinct=True),
        )
        .order_by('year')
    )
    serializer_class = TrackingSerializer

序列化器

class VenueSerializer(serializers.ModelSerializer):
    class Meta:
        model = Venue
        fields = ['id', 'name']

    def to_representation(self, value):
        value = Venue.objects.get(pk=value)
        return super(VenueSerializer, self).to_representation(value)


class TrackingSerializer(serializers.ModelSerializer):
    venue = VenueSerializer(read_only=True)
    year = serializers.IntegerField(read_only=True)
    count = serializers.IntegerField(read_only=True)

    class Meta:
        model = Tracking
        fields = ['venue', 'year', 'count']

请注意,我用TruncYear替换了ExtractYear,两者之间的区别在于前者返回日期时间,后者返回的是您想要的int。

如果您想使用TruncYear,则必须替换:

year = serializers.IntegerField(read_only=True)

with:

year = serializers.DateTimeField(read_only=True)

TrackingSerializer中。

© www.soinside.com 2019 - 2024. All rights reserved.