Reputation: 2699
Can I have a model field be based on other fields? For example:
class Foo(models.Model):
x = models.PositiveSmallIntegerField()
y = models.PositiveSmallIntegerField()
z = models.PositiveSmallIntegerField()
score = models.PositiveSmallIntegerField(default=x+y+z)
Upvotes: 12
Views: 12304
Reputation: 16072
As of Django 5.0, GeneratedField
is the best solution to your problem.
The docs on GeneratedField
:
A field that is always computed based on other fields in the model. This field is managed and updated by the database itself. Uses the GENERATED ALWAYS SQL syntax.
from django.db import models
from django.db.models import F
class Foo(models.Model):
x = models.PositiveSmallIntegerField()
y = models.PositiveSmallIntegerField()
z = models.PositiveSmallIntegerField()
score = models.GeneratedField(
expression = F('x') + F('y') + F('z'),
output_field = models.IntegerField(),
db_persist = True
)
Upvotes: 2
Reputation: 155
How about this?
class Foo(models.Model):
x = models.PositiveSmallIntegerField()
y = models.PositiveSmallIntegerField()
z = models.PositiveSmallIntegerField()
@property
def score(self):
return self.x + self.y + self.z
Official docs on Model Methods here
Upvotes: 10
Reputation: 99680
Yes, the best way to handle this would be to override the save
method of the model
class Foo(models.Model):
x = models.PositiveSmallIntegerField()
y = models.PositiveSmallIntegerField()
z = models.PositiveSmallIntegerField()
score = models.PositiveSmallIntegerField()
def save(self, *args, **kwargs):
self.score = self.x + self.y + self.z
super(Foo, self).save(*args, **kwargs) # Call the "real" save() method.
Make sure you take care of the necessary validations.
More on this here: official documentation
Upvotes: 25