Currently my Django models looks like this:
class Car(Model):
horse_power = IntegerField()
I have lots of models similar to this, they are used all over the application, there are serializers of DRF endpoints using these model fields as well. Of course the field names are different in other models.
However, the horse_power
value as well as other fields are no longer IntegerField
, but a foreign key to another table containing more complex information like below:
class Car(Model):
horse_power_complex = OneToOneField(ComplexDataModel, on_delete=CASCADE)
To avoid lots of code change in every place the Car
model is manipulated, I would like to keep the same getter and setter interfaces as before, in other words, I would like car.horse_power
to return a simple integer calculated from the ComplexDataModel, and I also would like car.horse_power = 23
to access the ComplexDataModel and save the processed data so that I dont have to go over the entire application to update all references.
It is important to keep in mind that the model constructor should still work, for example, car = Car(horse_power=50)
.
I have tried python descriptors like below:
class HorsePower:
def __get__(self, obj, objtype=None):
return obj.horse_power_complex.get_value()
def __set__(self, obj, value):
obj.horse_power_complex.set_value(value)
class Car(Model):
horse_power = HorsePower()
horse_power_complex = OneToOneField(ComplexDataModel, on_delete=CASCADE)
This approach works well in most cases, but it fails to instantiate a new Car
because the constructor does not accept non-django-field arguments.
Please do not question the reason it has to be made complex, because it really is complex, the car and horse power was just a way to make the example look clean and not confuse you with weird scientific terms
CodePudding user response:
Use a property
class Car( Model)
horse_power_complex = ...
@property
def horse_power(self): # getter
return self.horse_power_complex.get_value()
@horse_power.setter
def horse_power( self, value):
self.horse_power_complex.set_value(value)