1

I want to write a custom QuerySet and Manager for a model that has a DateTimeField("installed_date" field) and an IntegerField ("expiration_days"), and I want to filter objects based on the rule " 'installed_date' plus 'expiration_days' is prior to current day" so to get objects that are currently due.

For example:

import datetime as dt
from django.db import models
from django.db.models import F, Func, ExpressionWrapper, DateField, IntegerField, FloatField
from django.utils import timezone

class MyQuerySet(models.QuerySet):
    def obsolete(self):
        current_date = timezone.localtime(timezone.now())
        obsolete_qs = self.annotate(
            days_since_installed_date = ExpressionWrapper(
                F('installed_date')-current_date, output_field='IntegerField'
            )
        ).filter(
            days_since_installed_date__lt=F('expiration_days')
        )
    return obsolete_qs

class MyManager(models.Manager):
    def get_queryset(self):
    return MyQuerySet(self.model, using=self._db)
    def obsolete(self):
        return self.get_queryset().obsolete()

class MyModel(models.Model):
    description = models.CharField(max_length=100)
    installed_date = models.DateTimeField(default=timezone.now)
    expiration_days = models.PositiveIntegerField()

    obsolete = MyManager()

    @property
    days_since_installed_date = installed_date - timezone.now()

When trying as before i get the error "'str' object has no attribute 'get_lookup'"

Also tried this:

class MyQuerySet(models.QuerySet):
    def obsolete(self):
        current_date = timezone.localtime(timezone.now())
        obsolete_qs = self.annotate(
            days_since_installed_date = F('installed_date')-current_date
        ).filter(
            expiration_days__gt=days_since_installed_date
        )
    return obsolete_qs

Here I get "name 'days_since_installed_date' is not defined". If I encapsulate 'days_since_installed_date' in an F() expression inside the filter portion of the previous code i get "operator does not exist: integer > interval".

And I've been trying a few more recipes based on StackOverflow answers but still getting all sort of errors.

I am using Python 3.5, Django 1.11 and Postgres.

Can anyone suggest an approach ?

(Plus, If anyone can reference a tutorial on querying django db based on dates would be greatly appreciated)

naccode
  • 510
  • 1
  • 8
  • 18
  • You could try adding the expiration days to the installation date to get an expiration datetime, then compare that to the current date. Similar to the example [in the docs](https://docs.djangoproject.com/en/2.0/ref/models/expressions/#using-f-with-annotations). – Alasdair Mar 07 '18 at 15:59
  • @Alasdair I tried that. Got an error:"operator does not exist: timestamp with time zone + integer" – naccode Mar 07 '18 at 16:28

0 Answers0