How to Add a Calculated Field to a Django Model

How to add a calculated field to a Django model

Ok... Daniel Roseman's answer seemed like it should have worked. As is always the case, you find what you're looking for after you post the question.

From the Django 1.5 docs I found this example that worked right out of the box. Thanks to all for your help.

Here is the code that worked:

from django.db import models
from django.contrib import admin

class Employee(models.Model):
lastname = models.CharField("Last", max_length=64)
firstname = models.CharField("First", max_length=64)
middlename = models.CharField("Middle", max_length=64)
clocknumber = models.CharField(max_length=16)

def _get_full_name(self):
"Returns the person's full name."
return '%s, %s %s' % (self.lastname, self.firstname, self.middlename)
full_name = property(_get_full_name)

class Meta:
ordering = ['lastname','firstname', 'middlename']

class EmployeeAdmin(admin.ModelAdmin):
list_display = ('clocknumber','full_name')
fieldsets = [("Name", {"fields":(("lastname", "firstname", "middlename"), "clocknumber")}),
]

admin.site.register(Employee, EmployeeAdmin)

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.

Derived (Calculated) Field From Another Model

You can use @property decorator for that, to give you an example:

class Salary(models.Model):
person_id = models.ForeignKey(
Person,
on_delete=models.CASCADE,
)

@property
def name(self):
return self.person_id.name if self.person_id else None

@property
def income_in_euro(self):
if not self.person_id:
return
return Jobs.objects.filter(person_id_id=self.person_id_id).first(). job_income_in_usd * 0.89

btw i do not think its a good idea naming your ForeignKeys with _id at the end.

Django Model field calculated from other fields

Figured it out (w the help of AbhiP!) Python int typecasting was the main culprit. Stupid problem to have!

Below is what worked, and allowed me to not save the calculated field (but display it and make it act like a field in the model):

@property
def yield_num(self):
if self.starts > 0:
#needed the float() to cast it out of an int
return self.finishes / float(self.starts)
else:
return 0

How to add a calculated field to a django admin inline

I wound up having to use a custom ModelForm in the inline. I did it like this:

admin.py:

class MyMembershipInlineForm(forms.ModelForm):
class Meta:
model = MyUser.groups.through
fields = ("group", )
readonly_fields = (
"timestamp",
"size",
)
size = forms.IntegerField(disabled=True)

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
my_membership = self.instance
self.initial = {
"size": my_membership.group.size if my_membership.pk else None
}

class MyMembershipInline(admin.TabularInline):
model = MyUser.groups.through
fields = (
"group",
"timestamp",
"size",
)
form = MyMembershipInlineForm

@admin.register(MyUser):
class MyUserAdmin(admin.ModelAdmin)
fields = ("user_name",)
inlines = (MyMembershipInline,)

How do I easily create a calculated field in a Django model?

I think the easiest way is to override the save method. I don't see any reason why it should save to the database twice.

class SoftwareHelp(Help):
about_software = models.ForeignKey('Software')

def save(self, *args, **kwargs):
self.about_software = 'Help for %s' % self.title
return super(SoftwareHelp, self).save(*args, **kwargs)

How to add a calculated field to a django query expression

I was able to solve my problem using Django's db function Extract (https://docs.djangoproject.com/en/3.1/ref/models/database-functions/#extract)

My DocumentCommentManager:

from django.db.models.functions import Extract

class DocumentCommentManager(models.Manager):
def get_queryset(self):
return super(DocumentCommentManager, self).get_queryset().annotate(created_year=Extract("created","year"))

This solves my original problem of adding a calculated datetime field to the model queries.

I still have not found a general way to add a calculated field to a model query using Q expressions. If you can share any examples, that would be great!



Related Topics



Leave a reply



Submit