Table of Contents
Django, just released its new major version, django 5.0, and one of the features that gained everyone's eyes is GeneratedField
. Remember model managers, that we used to apply business logic to database fields? GeneratedFields are like that. You can use them to get business logic to database layer which is most of times - the lowest level of your app.
You can try out django 5.0 by installing it with the following command - python3 -m pip install django==5.0rc1
If you want to try Django 5.0 or its upcoming version, you would want to have python>=3.10 in your system. Django 4.2.x was the last series to support python 3.8 and 3.9. See more about it here
GeneratedField
's lore
Earlier we used methods inside our models to filter common business queries in our model itself, like this:
from django.db import models
class Post(models.Model):
title = models.CharField(max_length=70)
# ...
def get_howto_guides(self):
return Post.objects.filter(title__istartswith="how to")
or we can use Managers like this,
from django.db import models
class HowtoPostsManager(models.Manager):
def get_queryset(self):
return super().get_queryset().filter(title__istartswith="how to")
# istartswith lookup field is used to
# lookup case-insensitive titles.
class Post(models.Model):
# ...
objects = models.Manager() # Default Manager
how_to = models.HowtoPostsManager() # our custom manager
Now Post.objects.all()
, will return all the posts from the database, while Post.how_to.all()
, will return only posts whose title starts with “How to”.
Now GeneratedField
comes into play. Look at this scenario where there is a model named Booking
.
from django.db import models
class Booking(models.Model):
start_date = models.DateField()
end_date = models.DateField()
Here if I want to calculate the total duration of Booking
, I will implement it like this,
from django.db import models
class Booking(models.Model):
start_date = models.DateField()
end_date = models.DateField()
def duration(self):
return self.end_date - self.start_date
Or, I can use a model manager, like this,
from django.db import models
from django.db.models import F
class DurationManager(models.Manager):
def get_queryset(self):
return super().get_queryset().annotate(duration=F("end_date")-F("start_date"))
class Booking(models.Model):
start_date = models.DateField()
end_date = models.DateField()
objects = DurationManager()
But, with both of these options, the field duration
doesn't exist on database, so I can't index it. This is where GeneratedField
comes in.
I can use GeneratedField
to create a field duration
on my Booking
model, which will be kept up-to-date automatically by database. I can also choose to persist this in the database, which means I can index it.
from django.db import models
from django.db.models import F
class Booking(models.Model):
start_date = models.DateField()
end_date = models.DateField()
duration = models.GeneratedField(
expression=F("end_date")-F("start_date"),
output_field=models.DurationField(),
db_persist=True
)
TL;DR
GeneratedField
is a new Django 5.0 feature and has these characteristics:
- Its value is calculated entirely by the database
- It works in all supported backend databases
GeneratedField
The GeneratedField
are full-fledged fields that can be used in queries, displayed and even indexed but their values cannot be set or modified because they are automatically calculated by the database itself whenever the other fields of the same row are modified.
For this reason, they are very useful for having immediately available values calculated starting from the other fields of the same model as long as these are in the same database table.
The definition of the GeneratedField
class requires specifying the expression
, output_field
, and db_persist
attributes.
Attributes
- db_persist -
True
|False
- If set toTrue
, it will occupy database storage as if it were a real column. Can be used for indexing. - output_field - An explicit model field instance to define the generated fields datatype and its other attributes. Eg:
FloatField
,DateField
,DurationField
etc. - expression - The expression that the database will evaluate to automatically set the field value each time the model is changed.
References
- Django 5.0 Release Notes
- What's new in Django 5.0! - (Video) -> (Recommended to Subscribe)
- Database generated columns⁽¹⁾: Django & SQLite