我有一个带有自定义管理器的模型,目的是过滤“活动”对象,即比当前时间低start_date
且比当前时间大end_date
的对象。< / p>
这是我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 shell中运行良好。但是,如果我在管理界面中创建一个对象,并将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__lt
和end_date__gt
参数的相同值(我now()
后立即manage.py runserver
返回的值)。
即使我在资源类中进行过滤,这个问题仍然存在,如下所示:
class ActiveObjectResource(ModelResource):
...
class Meta:
queryset = Object.objects.\
filter(start_date__lt=now(), end_date__gt=now())
此外,如果我通过这样的callables,问题仍然存在:
class ActiveObjectResource(ModelResource):
...
class Meta:
queryset = Object.objects.filter(start_date__lt=now, end_date__gt=now)
有没有办法可以重写ActiveObjectManager
或ActiveObjectResource
来克服这个问题?
更新
好的,似乎我需要覆盖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 :(得分:3)
好吧,关于ModelResource.Meta
中的queryset。这是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()