2012-07-10 63 views
2

我有一个自定义管理器模型,目的是过滤“活动”对象,即对象的start_date低于当前时间和end_date大于当前时间。Tastypie资源没有显示新创建的对象(日期过滤问题)

这是我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() 

该管理整个应用程序,并在Django壳的伟大工程。但是,如果我在管理界面中创建一个对象,并将start_date设置为“now”选择器,则tastypie提供的API不会显示此新创建的对象(尽管它确实显示较旧的对象)。管理员列表正确显示新对象处于活动状态。

这是我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() 

我强烈怀疑的是,作为类ActiveObjectResource被解释一次,只执行一次夫妻now()呼叫,即API子系统始终呼叫filter(),参数start_date__ltend_date__gt的参数值相同(在运行manage.py runserver后立即由now()返回的值)。

当我在资源类中的滤波权这样这个问题仍然存在,甚至:

class ActiveObjectResource(ModelResource): 
    ... 
    class Meta: 
     queryset = Object.objects.\ 
      filter(start_date__lt=now(), end_date__gt=now()) 

而且,问题仍然存在,如果我通过可调用这样的:

class ActiveObjectResource(ModelResource): 
    ... 
    class Meta: 
     queryset = Object.objects.filter(start_date__lt=now, end_date__gt=now) 

是否有我可以重写ActiveObjectManagerActiveObjectResource来克服这个问题吗?

更新: OK,看来我需要重写get_object_list实现per-request alterations to the queryset,如:

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) 

可是,我讨厌重复这种逻辑的时候,我已经在模型级别有​​一个自定义的经理为我做这个工作。

所以我的问题是:如何使用我的自定义模型管理器从我的ModelResource

+0

我在黑暗中拍摄在这里,因为我不是100%肯定这一点。不过,我的猜测是,由于多次调用'Object.active_objects.all()'在技术上仍然是*相同的查询集,所以查询缓存正在发挥作用。与此同时,'Object.objects.filter(...)'表面上显然是一个不同的查询,因此每次调用时都会使查询缓存失效。 – 2012-07-10 14:42:50

+0

@ChrisPratt根据'get_query_set'中定义的内容,对'Object.active_objects.all()'的多次调用产生不同的查询集,并且通过在shell中手动调用该管理器按预期工作来证明这一点。问题是'Object.active_objects.all()'被称为_only once_。 – Chewie 2012-07-10 16:42:10

+0

我已经更新了我的答案 – DataGreed 2012-07-20 07:49:53

回答

3

那么,关于queryset在ModelResource.Meta。这里是excerpt from the tastypie documentation

如果你放置任何可调对象在这,他们只会被评估一次(当Meta类被实例化时)。这尤其影响与日期/时间相关的事物。请参阅:ref:cookbook来解决这个问题。

it goes这里:

一个常见的图案需要的东西每个请求例如日期/时间改变,以限制查询集。你可以通过轻微修改来实现这一点get_object_list

所以,是的,似乎唯一的方法来实现你想要做的是声明get_object_list

新更新:因为get_object_list只是一个return self._meta.queryset._clone(),尝试类似的东西:

class ActiveObjectResource(ModelResource): 
    class Meta: 
     queryset = Object.objects_active.all() 

    def get_object_list(self, request): 
     return Object.objects_active.all() 
+0

是的,这正是我最终做的,有点。我这样做:'self._meta.queryset = NewsGroup.objects_active.all();返回超级(NewsGroupAssignationResource,self).get_object_list(request)'。这有点怪异('Meta.queryset'的值完全没用),但完成了工作。 – Chewie 2012-07-20 11:20:14