Simon
Simon

Reputation: 1719

Django - Filter based on model method

I have a model, defined like this :

class Item(models.Model):
    name = models.CharField(max_length=200, null=True, default='', blank=True)
    creation_date = models.DateTimeField('date created', default=timezone.now())

    def was_published_today(self):
        today = timezone.now() - datetime.timedelta(days=1)
        return self.creation_date >= today

I would like to filter a set of Item like this :

items = Item.objects.filter(was_published_today=True)

But I run into a FieldError which makes sense as it seems that filter is not made to filter a set of objects based on a method. Detailed error :

Cannot resolve keyword 'was_published_today' into field. Choices are : creation_date, name

What is the correct way to do this ? I know I can compare creation_date with today's date but that's what was_published_today does and I would like to keep it DRY.

Upvotes: 0

Views: 3868

Answers (2)

ruddra
ruddra

Reputation: 52028

Here you can use django Managers.

Custom Manager:

class GetPublishedToday(models.Manager):
      def get_query_set(self):
        return super(GetPublishedToday, self).get_query_set().filter(creation_date= timezone.now() - datetime.timedelta(days=1))

in Models:

class Item(models.Model):
    name = models.CharField(max_length=200, null=True, default='', blank=True)
    creation_date = models.DateTimeField('date created', default=timezone.now())
    was_published_today= GetPublishedToday()

in views:

items = Item.was_published_today.all()  # or .filter(name= "foobar")

'''PS: Its an untested code.'''

Upvotes: 3

erthalion
erthalion

Reputation: 3244

F expressions is a correct way, I think. Example from documentation:

from datetime import timedelta
Entry.objects.filter(mod_date__gt=F('pub_date') + timedelta(days=3))

Upvotes: 0

Related Questions