你能修改for循环中的模型字段吗?

时间:2017-08-05 03:52:16

标签: python django

我试图编写一个转换温度单位的方法,这样我就可以按需显示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

0 个答案:

没有答案