Django 按最新的相关对象过滤

Posted

技术标签:

【中文标题】Django 按最新的相关对象过滤【英文标题】:Django Filter by latest related object 【发布时间】:2013-05-06 08:33:33 【问题描述】:

我已经设置了一个系统来跟踪数据库中各种对象的审核任务。这些通过通用外键关系链接。给定一个 ObjectModerationState 对象,我必须从最近的 StateTransisition 对象中确定其状态。

该解决方案必须将其用于 SimpleListFilter 中,以便使用 list_filter 在 list_display 上进行排序。

例如给定状态 - 排队 - 完全的 - 验证

我应该能够根据 StateTransisition 对象中的最新状态值过滤 ObjectModerationState 对象。

我一直倾向于对 ObjectModerationState 进行某种注释。

这就是我所拥有的不起作用的东西。

models.py:

class ObjectModerationState(models.Model):
    job = models.ForeignKey(JobDescription)
    object_id = models.TextField(help_text="Primary key of the model under moderation.")
    content_type = models.ForeignKey(ContentType, help_text="Content type of the model under moderation.")
    object = generic.GenericForeignKey()

class StateTransisition(models.Model):
    state = models.ForeignKey(State)
    moderation_details = models.ForeignKey("ObjectModerationState", related_name='states')
    changed_by = models.ForeignKey("auth.User", related_name='+', null=False,
                                   help_text="If you create the task, then usually this will be you.")
    date_updated = models.DateTimeField(_("Date Set"))
    last_modified = models.DateTimeField(auto_now=True)


    def __unicode__(self):
        return "%s in state %s by %s" % (self.moderation_details.object, self.state, self.changed_by)

    class Meta:
        ordering = ['last_modified', ]
        get_latest_by = 'last_modified'

class State(Orderable):
    label = models.CharField(_("State Label"), max_length=100, unique=True)
    description = models.TextField(_("Description"), max_length=200, null=True, blank=True,
                                   help_text=_("Explination of this state in context"))
    valid_transitions = models.ManyToManyField("State", null=True, blank=True,
                                               help_text=_("You must add these mappings."))

    def __unicode__(self):
        return "%s" % (self.label)

    class Meta:
        abstract = False

admin.py

class CurrentStateFilter(SimpleListFilter):
    title = 'current state'
    parameter_name = 'current state'

    def lookups(self, request, model_admin):
        states = State.objects.all()
        return  [(c.id, c) for c in states]

    def queryset(self, request, queryset):
        if self.value():
            queryset.filter(states__state__id=self.value()) <<< ????
        else:
            return queryset

编辑

我相信问题与此类似,如果解决方案正确,似乎无法解决。 complex annotate on django query set

【问题讨论】:

也许最好的办法就是在 ObjectModerationState 模型中缓存最后一个状态和用户 【参考方案1】:

缓存绝对是解决这种情况的好方法。然而,为了完整起见,我想证明我已经能够使用以下 Django ORM 查询做同样的事情:

EventGroup.objects.annotate(
    latest_event_date=Max('events__timestamp')
).filter(
    events__timestamp=F('latest_event_date'),
    events__state=EventState.STATE_PROCESSED,
)

因此,对于每个EventGrouplatest_event_date 被注释为该组事件的最大值timestamp。此外,我过滤以仅包含EventGroups,其最新事件的状态为EventState.STATE_PROCESSED

我相当肯定这样的事情会适用于你的情况。

【讨论】:

【参考方案2】:

经过大量研究,我不确定它是否可以在没有非常 hacky 的情况下完成。我最终将值直接缓存在 list_display 中显示的模型上。我使用后保存信号做到了这一点。它工作得很好。

【讨论】:

以上是关于Django 按最新的相关对象过滤的主要内容,如果未能解决你的问题,请参考以下文章

Django 石墨烯,按对象过滤

Django ORM按两个相关模型的最大列值过滤

Django Queryset:按相关项目管理器过滤

Django ORM:按相关表过滤器的聚合排序

Django按模型对象列表过滤

Django:每个外键返回一个过滤对象