【发布时间】:2012-07-10 13:30:26
【问题描述】:
我有一个带有自定义管理器的模型,目的是过滤“活动”对象,即start_date 低于当前时间和end_date 高于当前时间的对象。
这是我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 设置为“现在”选择器,那么美味派提供的 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 参数(在我运行 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)
有没有办法可以重写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 中使用我的自定义模型管理器?
【问题讨论】:
-
我在这里在黑暗中拍摄,因为我对此不是 100% 确定的。尽管如此,我的猜测是,由于多次调用
Object.active_objects.all()仍然是技术上 相同的查询集,查询缓存正在发挥作用。同时,Object.objects.filter(...)表面上显然是一个不同的查询,因此每次调用它都会使查询缓存失效。 -
@ChrisPratt 不,根据
get_query_set中定义的内容,多次调用Object.active_objects.all()会产生不同的查询集,并通过在shell 中手动调用该管理器按预期工作的事实证明。问题是Object.active_objects.all()只被调用一次。