Ujjawal Anand
Ujjawal Anand

Reputation: 43

Filter data based on sum of two fields

I have following Django model

class OfflineExamResult(models.Model):
  """ Model to store result of offline exam """
  batch = models.CharField(max_length=40, null=True, blank=True)
  date = models.CharField(max_length=20, null=True, blank=True)
  full_marks = models.IntegerField(default=80)
  rank = models.CharField(max_length=5, null=True, blank=True)
  uid1 = models.CharField(max_length=10, null=True, blank=True)
  uid2 = models.CharField(max_length=10, null=True, blank=True)
  name = models.CharField(max_length=30, null=True, blank=True)
  marks = models.CharField(max_length=5, null=True, blank=True)

The students in my class have been allotted a roll number which is sum (string sum) of uid1 and uid2. I want to create a search field so that students enter their roll number and get their result which will happen, only if I am able to filter objects after comparing roll number to sum of uid1 and uid2.

Upvotes: 2

Views: 1180

Answers (2)

T.Tokic
T.Tokic

Reputation: 1254

Since your uid1 and uid2 are CharFields you need to use Cast database function if you want to perform arithmetical operations among CharFields.

This should work:

from django.db.models import F, IntegerField
from django.db.models.functions import Cast

students = OfflineExamResult.objects.annotate(uid1_int=Cast('uid1', IntegerField()), uid2_int=Cast('uid2', IntegerField())).annotate(roll=F('uid1_int') + F('uid2_int')).filter(roll=roll_number)

P.S.

I used IntegerField field in my example but if you have decimal numbers in the database you should use FloatField instead.

Upvotes: 2

Astik Anand
Astik Anand

Reputation: 13047

You need to use F() with annotation().

from django.db.models import F

students = OfflineExamResult.objects.annotate(roll=F('uid1') + F('uid2')).\
filter(roll=given_roll_number)

Upvotes: 4

Related Questions