I have a model with a custom manager with the purpose of filtering “active” objects, i.e. objects which have a start_date lower than the current time and an end_date greater than the current time.
This is the relevant part of my models.py:
from django.utils.timezone import now
class ActiveObjectManager(models.Manager):
def get_query_set(self):
return super(ActiveObjectManager, self).get_query_set().\
filter(start_date__lt=now(), end_date__gt=now())
class Object(models.Model):
start_date = models.DateTimeField(_('Service start date'), \
auto_now_add=False, null=False, blank=False)
end_date = models.DateTimeField(_('Service end date'), auto_now_add=False, \
null=False, blank=False)
...
objects = models.Manager()
objects_active = ActiveObjectManager()
This manager works great across the application and in a Django shell. However, if I create an object in the admin interface, and set the start_date to the “now” selector, the API provided by tastypie isn’t showing this newly created object (though it does show older objects). The admin list correctly shows the new object as active.
This is the relevant part of my api.py:
from app.models import Object
class ActiveObjectResource(ModelResource):
modified = fields.BooleanField(readonly=True)
class Meta:
resource_name = 'activeobjects'
queryset = Object.objects_active.all()
My strong suspicion is that, as the class ActiveObjectResource is being interpreted once, the couple of now() calls are only being executed once, i.e., the API subsystem is always calling filter() with the same values for the start_date__lt and end_date__gt parameters (the value returned by now() immediately after I run manage.py runserver).
This problem persists even when I do the filtering right in the resource class like this:
class ActiveObjectResource(ModelResource):
...
class Meta:
queryset = Object.objects.\
filter(start_date__lt=now(), end_date__gt=now())
Also, the problem persists if I pass callables like this:
class ActiveObjectResource(ModelResource):
...
class Meta:
queryset = Object.objects.filter(start_date__lt=now, end_date__gt=now)
Is there a way I can rewrite ActiveObjectManager or ActiveObjectResource to overcome this?
Update:
OK, it seems I need to override get_object_list to achieve per-request alterations to the queryset, like:
class ActiveObjectResource(ModelResource):
class Meta:
queryset = Object.objects.all()
def get_object_list(self, request):
return super(MyResource, self).get_object_list(request).\
filter(start_date__lt=now, end_date__gt=now)
But I hate to duplicate this logic when I already have a custom manager at the model level to do this work for me.
So my question is: how can I use my custom model manager from within my ModelResource?
Well, about queryset in
ModelResource.Meta. Here’s the excerpt from the tastypie documentation:Here it goes:
So, yeah, seems like the only way to achieve what you are trying to do is to declare
get_object_list.New Update: since
get_object_listis just areturn self._meta.queryset._clone(), try something like that: