如何使用Django 1.11中queryset TruncYear生成的对象关系序列化列表



我设法用TruncYear/TruncMonth/TruncDay/等从跟踪表中获取时间序列数据,如下所示。然而,场馆的数据只是产生venue_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框架在不创建模型的情况下序列化字典

仅供参考,这是我测试的实际代码(也必须放在这里(,名称可能略有不同,但整个意图是相同的。https://gist.github.com/axilaris/919d1a20d3e799101a8cf6aeb4d120b5

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

在您的情况下,还需要考虑一些问题:由于您使用values进行分组,因此从查询集获得的不是Tracking对象,因此DRF无法将venue_id转换为Venue对象。

要解决此问题,您需要重写VenueSerializerto_representation方法,以从其主键获取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']

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

如果您更喜欢使用TruncYear,则必须更换:

year = serializers.IntegerField(read_only=True)

带有:

year = serializers.DateTimeField(read_only=True)

在CCD_ 14中。

最新更新