I have a model Student
with manager StudentManager
as given below. As property gives the last date by adding college_duration
in join_date
. But when I execute this property computation is working well, but for StudentManager
it gives an error. How to write manager class which on the fly computes some field using model fields and which is used to filter records.
The computed field is not in model fields. still, I want that as filter criteria.
class StudentManager(models.Manager):
def passed_students(self):
return self.filter(college_end_date__lt=timezone.now())
class Student(models.Model):
join_date = models.DateTimeField(auto_now_add=True)
college_duration = models.IntegerField(default=4)
objects = StudentManager()
@property
def college_end_date(self):
last_date = self.join_date + timezone.timedelta(days=self.college_duration)
return last_date
Error Django gives. when I tried to access Student.objects.passed_students()
django.core.exceptions.FieldError: Cannot resolve keyword 'college_end_date' into field. Choices are: join_date, college_duration
By using the
annotate(...)
--(Django Doc) oralias(...)
(New in Django 3.2) if you're using the value only as a filter.Because the model managers (more accurately, the
QuerySet
s) are wrapping things that are being done in the database. You can call the model managers as a high-level database wrapper too.But, the property
college_end_date
is only defined in your model class and the database is not aware of it, and hence the error.Using
annotate(...)
method is the proper Django way of doing so. As a side note, a complex property logic may not be re-create with theannotate(...)
method.In your case, I would change
college_duration
field fromIntegerField(...)
toDurationField(...)
--(Django Doc) since its make more sense (to me)Later, update your manager and the properties as,
Note:
DurationField(...)
will work as expected in PostgreSQL and this implementation will work as-is in PSQL. You may have problems if you are using any other databases, if so, you may need to have a "database function" which operates over the datetime and duration datasets corresponding to your specific database.Personally, I like this solution,