Let's say I have this following model:
class Product(models.Model):
price = models.DecimalField(
max_digits=19,
decimal_places=4,
validators=[MinValueValidator(0)],
blank=False,
null=False,
)
expiry_date = models.DateTimeField(
blank=True,
null=True,
)
@property
def price_in_cents(self):
return round(self.price * 100)
@property
def has_expired(self):
if self.expiry_date:
return date.today() > self.expiry_date.date()
else:
return False
So two fields, and two other properties that rely on these two fields to generate an output. I'm trying to convert these fields into generated fields (for Django 5). My first understanding was simply just putting in the property function in the expression, so something like this:
class Product(models.Model):
price = models.DecimalField(
max_digits=19,
decimal_places=4,
validators=[MinValueValidator(0)],
blank=False,
null=False,
)
price_in_cents = models.GeneratedField(
expression=round(F("price") * 100),
output_field=models.BigIntegerField(),
db_persist=True,
)
expiry_date = models.DateTimeField(
blank=True,
null=True,
)
@property
def has_expired(self):
if self.expiry_date:
return date.today() > self.expiry_date.date()
else:
return False
Unfortunately, this does not seem to work, and I get the following error:
TypeError: type CombinedExpression doesn't define round method
Going by this, I assume I won't be able to simply convert the second property either. So how would this actually work? Is there a resource to help me convert these Python functions (properties) into valid expressions?
You should use database query function Round
:
from django.db import models
from django.db.models.functions import Round
# Create your models here.
class Product(models.Model):
price = models.DecimalField(
max_digits=19,
decimal_places=4,
validators=[MinValueValidator(0)],
blank=False,
null=False,
)
price_in_cents = models.GeneratedField(
expression=Round(F("price") * 100),
output_field=models.BigIntegerField(),
db_persist=True,
)
expiry_date = models.DateTimeField(
blank=True,
null=True,
)
@property
def has_expired(self):
if self.expiry_date:
return date.today() > self.expiry_date.date()
else:
return False