Django Model Method or Calculation as Field in Database

You have to override the save method of yout Model Person and create unique_id and age field in the Model.

from dateutil.relativedelta import relativedelta
from datetime import datetime

class Person(model.Model)
     unique_id = models.CharField(max_length=25)
     age = models.IntegerField()
     last_name = models.CharField(max_length=25)
     birth_date = models.DateField()
     city_of_birth = models.CharField(max_length=25)
 
     @property
     def get_unique_id(self):
         a = self.last_name[:2].upper()     #First 2 letters of last name
         b = self.birth_date.strftime('%d')     #Day of the month as string
         c = self.city_of_birth[:2].upper()     #First 2 letters of city
         return a + b + c 
 
     @property
     def get_age(self):
         return relativedelta(self.birth_date.days, datetime.date.now()).years
     

     def save(self, *args, **kwargs):
          self.unique_id = self.get_unique_id
          self.age = self.get_age
          super(Person, self).save(*args, **kwargs)

UPDATE: Previously the self.get_unique_id and self.get_age were being called with '()' which is not required for class properties.


A model has a clean method for this kind of thing:

This method should be used to provide custom model validation, and to modify attributes on your model if desired. For instance, you could use it to automatically provide a value for a field, or to do validation that requires access to more than a single field

So loose the property and add a field named 'unique_id' which should be a CharField. Rename get_id to clean and replace the return statement with:

self.unique_id = a + b + c

If you're certain this always generates a unique string, consider making this field the primary key. However, if this model is already migrated, you cannot name it id, since Django has already created a field id as an AutoField for you, so it will take two migrations if you're set on the name 'id' (which you can squash later).