【问题标题】:Tastypie resource not showing newly created objects (date filtering issue)Tastypie 资源未显示新创建的对象(日期过滤问题)
【发布时间】: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__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 来克服这个问题?

更新: 好的,看来我需要覆盖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()只被调用一次

标签: python django tastypie


【解决方案1】:

好吧,关于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()

【讨论】:

  • 是的,这正是我最终做的,有点。我正在这样做:self._meta.queryset = NewsGroup.objects_active.all(); return super(NewsGroupAssignationResource, self).get_object_list(request)。这有点 hacky(Meta.queryset 值完全没用),但可以完成工作。
猜你喜欢
  • 2019-06-16
  • 1970-01-01
  • 2021-10-23
  • 1970-01-01
  • 1970-01-01
  • 2012-10-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多