我试图编写一个转换温度单位的方法,这样我就可以按需显示si单位而无需修改数据库。
当我加载视图时,Currently
正确转换,因为它没有在for循环中完成。
我遇到的问题是Hourly
。在for循环范围内修改data
并不会更改实际对象,但我不确定如何修改temperature
,因为我无法访问切片索引或像我在其他解决方案中看到的常规列表一样。
models.py
class DataPoint(models.Model):
... # Other fields
temperature = models.FloatField(null=True, blank=True)
def convert_f_to_c(self, temperature_f):
if temperature_f is not None:
return float("{0:.2f}".format((temperature_f - 32) * .5556))
return temperature_f
def get_si_units(self):
self.convert_f_to_c(self.temperature)
class Meta:
abstract = True
class DataBlock(models.Model):
"""
Abstract model that provides base weater information block.
"""
icon = models.CharField(blank=True, max_length=50)
summary = models.CharField(blank=True, max_length=200)
class Meta:
abstract = True
class Currently(DataPoint):
pass
class Hourly(DataBlock):
pass
class HourlyPoint(DataPoint):
hourly = models.ForeignKey(
Hourly,
on_delete=models.CASCADE,
related_name='data'
)
class Location(model.Model):
... # Other fields
currently = models.ForeignKey(Currently)
hourly = models.ForeignKey(Hourly)
def get_si_units(self):
self.currently.get_si_units() # modifies the location
for data in self.hourly.data.all():
data.get_si_units() # doesn't modify the location object
views.py
class SomeView(APIView):
def get(self, request, *args, **kwargs):
...
location = Location.objects.get(latitude, longitude)
location.get_si_units()
return LocationSerializer(location).data
serializers.py
class LocationSerializer(serializers.ModelSerializer):
"""
Serializes Location model data.
"""
currently = CurrentlySerializer()
hourly = HourlySerializer()
daily = DailySerializer()
class Meta:
model = Location
fields = (
'id',
'latitude',
'longitude',
'timezone',
'last_updated',
'currently',
'hourly',
'daily',
)
def create(self, validated_data):
# Create weather data required by Location.
currently_data = validated_data.pop('currently')
currently = Currently.objects.create(**currently_data)
hourly_pk = self.create_data_block(
validated_data, 'hourly', Hourly, HourlyPoint, 'hourly_id')
daily_pk = self.create_data_block(
validated_data, 'daily', Daily, DailyPoint, 'daily_id')
# Create Location data and return it.
location = Location.objects.create(
currently_id=currently.pk,
hourly_id=hourly_pk,
daily_id=daily_pk,
**validated_data
)
return location
def update(self, instance, validated_data):
# Update all weather data.
# Update Currently data.
currently = self.update_data(
validated_data,
'currently',
Currently,
instance.currently.id,
CurrentlySerializer)
# Update Hourly data.
hourly = self.update_data(
validated_data,
'hourly',
Hourly,
instance.hourly.id,
HourlySerializer,
)
# Update Daily data.
daily = self.update_data(
validated_data,
'daily',
Daily,
instance.daily.id,
DailySerializer,
)
# Update Location instance and return it.
instance.currently = currently
instance.hourly = hourly
instance.daily = daily
instance.save()
return instance
def create_data_block(self, data, block_str, DataBlock, DataPoint, id):
# Creates data block and data points associated with it
block_data = data.pop(block_str)
points_data = block_data.pop('data')
block = DataBlock.objects.create(**block_data)
for point_data in points_data:
DataPoint.objects.create(**{id: block.pk, **point_data})
return block.pk
def update_data(self, validated_data, data_str, Model, id, Serializer):
# Updates data for a given object
data = validated_data.pop(data_str)
object = Model.objects.get(id=id)
serializer = Serializer(object, data=data)
serializer.is_valid(raise_exception=True)
serializer.save()
return object