Home > Software design >  Django - Calculating age until a date in DB
Django - Calculating age until a date in DB

Time:10-04

I'm new to Django. Please help me with this issue.

This is the model that I want to write query on.

class ReservationFrame(models.Model):
    id = models.AutoField(primary_key=True)
    start_at = models.DateTimeField(db_index=True)
    information = models.JSONField(default=dict)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

The json field (ReservationFrame.information) has this format

{
    upper_age_limit: 22,
    lower_age_limit: 30
}

I want to calculate the age of login user until ReservationFrame.start_at, and return the corresponding ReservationFrame if upper_age_limit <= user.age <= lower_age_limit

The formula that I'm using to calculate age is

start_at.year - born.year - ((start_at.month, start_at.day) < (born.month, born.day))

I'm using annotate but getting errors.

person_birthday = request.user.person.birthday
frames_without_age_limit = reservation_frames.exclude(Q(information__has_key = 'upper_age_limit')&Q(information__has_key = 'lower_age_limit'))
reservation_frames = reservation_frames.annotate(
    age=ExtractYear('start_at') - person_birthday.year - Case(When((ExtractMonth('start_at'), ExtractDay('start_at')) < (person_birthday.month, person_birthday.day), then=1), default=0))
reservation_frames = reservation_frames.filter(
    Q(information__lower_age_limit__lte = F('age'))|
    Q(information__lower_age_limit=None)
)
reservation_frames = reservation_frames.filter(
    Q(information__upper_age_limit__gte = F('age'))|
    Q(information__upper_age_limit=None)
)

TypeError: '<' not supported between instances of 'ExtractMonth' and 'int'

CodePudding user response:

The Relational operators like <,>, <=,>=,== are not allowed in Django conditional expressions. So you should implement your logic using querysets and chain conditions. also, you can change that lexical comparison into a simpler logical comparison. like this:

(A,B) < (X,Y) ---> (A<X) OR ((A==X) AND (B<Y))

try like this. it should work!

reservation_frames = reservation_frames.annotate(
age=ExtractYear('start_at') - person_birthday.year - Case(
    When(Q(start_at__month__lt=person_birthday.month)|(Q(start_at__month=person_birthday.month) & Q(start_at__day__lt=person_birthday.day)), then=1),
    default=0))
  • Related