如何使用 Django 1.11 中的查询集 TruncYear 生成的对象关系序列化列表
How can I serialize list with an object relation produced from queryset TruncYear in Django 1.11
我设法使用 TruncYear/TruncMonth/TruncDay/etc 从跟踪 table 中获取时间序列数据,如下所示。但是场地的数据只产生 venue_id。我想将该序列化,以便它 return 是关系地点 table.
中的 "name"
我正在使用 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
}
]
我想将场地数据分解为 return 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 和名称从 "venue" 分解为 return?该名称可用于演示目的。
更新(这里有一些失败的尝试):
这只显示计数但累积(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)
我觉得答案很接近这个:
仅供参考,这是我用于测试的实际代码(也必须放在这里),名称可能略有不同,但整个意图是相同的。 https://gist.github.com/axilaris/919d1a20d3e799101a8cf6aeb4d120b5
您需要为显示 id
和 name
字段的 Venue 创建序列化程序,并将其用作 TrackingSerializer
.
中的字段
在你的情况下,还有一些事情需要考虑:因为你使用 values
进行分组,你从查询集中得到的不是 Tracking
对象,因此你的 venue_id
无法通过 DRF 转换为 Venue
对象。
要解决此问题,您需要重写 VenueSerializer
的 to_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']
注意我把你的TruncYear
换成了ExtractYear
,两者的区别在于前者returns是一个datetime,后者是一个int,我猜这就是你想要的.
如果您更喜欢使用 TruncYear
,则必须更换:
year = serializers.IntegerField(read_only=True)
与:
year = serializers.DateTimeField(read_only=True)
在 TrackingSerializer
.
我设法使用 TruncYear/TruncMonth/TruncDay/etc 从跟踪 table 中获取时间序列数据,如下所示。但是场地的数据只产生 venue_id。我想将该序列化,以便它 return 是关系地点 table.
中的 "name"我正在使用 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
}
]
我想将场地数据分解为 return 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 和名称从 "venue" 分解为 return?该名称可用于演示目的。
更新(这里有一些失败的尝试):
这只显示计数但累积(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)
我觉得答案很接近这个:
仅供参考,这是我用于测试的实际代码(也必须放在这里),名称可能略有不同,但整个意图是相同的。 https://gist.github.com/axilaris/919d1a20d3e799101a8cf6aeb4d120b5
您需要为显示 id
和 name
字段的 Venue 创建序列化程序,并将其用作 TrackingSerializer
.
在你的情况下,还有一些事情需要考虑:因为你使用 values
进行分组,你从查询集中得到的不是 Tracking
对象,因此你的 venue_id
无法通过 DRF 转换为 Venue
对象。
要解决此问题,您需要重写 VenueSerializer
的 to_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']
注意我把你的TruncYear
换成了ExtractYear
,两者的区别在于前者returns是一个datetime,后者是一个int,我猜这就是你想要的.
如果您更喜欢使用 TruncYear
,则必须更换:
year = serializers.IntegerField(read_only=True)
与:
year = serializers.DateTimeField(read_only=True)
在 TrackingSerializer
.