我有以下模型:
class Bus(models.Model):
bid = models.CharField(_("Bus unique id"), max_length=45)
plate_number = models.CharField(_("Plate number"), max_length=45)
class BusData(models.Model):
bus = models.ForeignKey(Bus, on_delete=models.CASCADE)
timestamp = models.DateTimeField()
speed = models.IntegerField(_("Speed"), null=True, blank=True)
我想用busdata一起检索总线对象,因此我使用下面的序列化器类。
class BusSerializer(serializers.ModelSerializer):
class Meta:
model = Bus
fields = ('bid', 'plate_number', 'busdata_set')
class BusDataSerializer(serializers.ModelSerializer):
class Meta:
model = BusData
到目前为止,BusSerializer输出如下所示:
In [8]: bus1 = Bus.objects.create(bid='1',plate_number='X101')
In [10]: from django.utils import timezone
In [15]: bus_data1 = BusData.objects.create(bus=bus1,timestamp=timezone.now(),speed=100)
In [18]: bus_data2 = BusData.objects.create(bus=bus1,timestamp=timezone.now(),speed=200)
In [20]: bus_s = BusSerializer(bus1)
In [21]: bus_s.data
Out[21]:
OrderedDict([('bid', u'1'),
('plate_number', u'X101'),
('busdata_set', [10, 11])])
如您所见,与此总线关联的busdatas已经在busdata_set字段中获取。
但是,我想要的是获取最新的busdata记录(按时间戳字段desc排序,并返回第一条记录),而不是所有的busdata记录。 看起来像这样,
OrderedDict([('bid', u'1'),
('plate_number', u'X101'),
('busdata', 11)])
我不知道如何实现这一目标。 任何想法和代码片段都会受到赞赏。 非常感谢!
答案 0 :(得分:1)
有很多方法可以做到这一点。最简单的方法是在Bus
类上有一个指向最新BusData
对象的属性,然后在序列化程序中检索它。
class Bus(models.Model):
bid = models.CharField(_("Bus unique id"), max_length=45)
plate_number = models.CharField(_("Plate number"), max_length=45)
@property
def bus_data(self):
return self.busdata_set.latest('timestamp')
然后在序列化程序中进行更改:
class BusSerializer(serializers.ModelSerializer):
bus_data = serializers.Field()
class Meta:
model = BusData
答案 1 :(得分:0)
作为Django-Rest-Framework Serialize Relations docs says您可以在PrimaryKeyRelatedField中定义查询集。所以你可以尝试这样:
class BusSerializer(serializers.ModelSerializer):
busdata_set = serializers.PrimaryKeyRelatedField(queryset=BusData.objects.create(bus=bus1,timestamp=timezone.now(),speed=200), many=True)
class Meta:
model = Bus
fields = ('bid', 'plate_number', 'busdata_set')