В настоящее время у меня есть две модели Django, определенные для DataUnit
(например, кВт-ч, $, день, месяц и т. Д.) И RateUnit
(например, $ / день, $ / кВт-ч и т. Д.).
Это оказывается полезным, так как я могу назначить единицы измерения различным значениям и гарантировать, что вычисления имеют смысл (например, X day * Y $ / day = $ Z), а также сделать недействительными вычисления, которые не следует делать (например,. DataUnit
не равен знаменателю RateUnit
).
Однако у меня есть кусок кода, который в настоящее время живет в Django и может быть полезен в общем контексте вне Django, ноопирается на RateUnit
и DataUnit
.
Могу ли я смоделировать что-то подобное в прямом Python?Я полагаю, что мог бы смоделировать DataUnit
, используя перечисление, и все же сохранить это значение перечисления в Django EnumField
.
Однако я не уверен, что делать с RateUnit
.Я хотел бы иметь возможность составлять единицу измерения из двух единиц данных (один числитель и один знаменатель) таким образом, чтобы они могли жить как самостоятельно в модуле Python, так и сохраняться в модели Django в поле.
class DataUnit(ValidationModel):
"""
Units of measure.
Ex. kw, kwh, therms
"""
name = models.CharField(max_length=8, unique=True)
class Meta:
ordering = ["id"]
def __str__(self):
return self.name
class RateUnit(ValidationModel):
"""
Units of rate.
Ex. $/kw, $/day, tCO2/kwh
"""
numerator = models.ForeignKey(
DataUnit, related_name="rate_unit_numerators", on_delete=models.PROTECT
)
denominator = models.ForeignKey(
DataUnit,
related_name="rate_unit_denominators",
on_delete=models.PROTECT,
)
class Meta:
ordering = ["id"]
unique_together = ("numerator", "denominator")
def __str__(self):
return "{}/{}".format(self.numerator, self.denominator)
Это пример того, как я использовал бы его для целей проверки.
def validate_units(count_unit, rate_unit):
"""
Validates that count_unit is a DataUnit and rate_unit is a RateUnit
and that multiplying them yields a dollar amount.
:param count_unit: DataUnit
:param rate_unit: RateUnit
"""
if not isinstance(count_unit, DataUnit) or not isinstance(
rate_unit, RateUnit
):
raise TypeError(
"count_unit must be a DataUnit and rate_unit must be a "
"RateUnit."
)
if (
count_unit != rate_unit.denominator
or rate_unit.numerator.name != "$"
):
raise TypeError(
"Multiplying count_unit by rate_unit must yield a dollar "
"amount."
)