SimpleListFilter调用两次,最后?e = 1

时间:2013-12-10 15:09:37

标签: python django filter django-admin django-1.4

我在django 1.4.3 [最终]中有一个管理页面。我们在很多硬件中使用CF卡,每张卡都连接到VPN。我有一个功能,可以根据数据库中写的最后反馈确定卡是否在线。

models.py:

class Card(models.Model):
    ...
    last_feedback = models.DateTimeField(_('Last feedback'), null=True, blank=True)

    ...
    def online_status(self):
            nowtime = calendar.timegm(timezone.now().utctimetuple())
            seen = calendar.timegm(self.last_feedback.utctimetuple())

            diff = nowtime-seen

            if (self.state == 1) and (diff < 300):
                    return '<div style="width:100%%; height:100%%; background-color:green; color:white;">online & production</div>'
            elif (diff < 300):
                    return '<div style="width:100%%; height:100%%; background-color:orange;">online</div>'
            else:
                    return "offline"
    online_status.allow_tags = True

admin.py:

class OnlineFilter(admin.SimpleListFilter):
    title = _("Online")
    parameter_name = "online"

    def lookups(self, request, model_admin):
            return (("yes", "Yes"),
                    ("no", "No"),
            )

    def queryset(self, request, queryset):
            out = self.filter(request, queryset)
            f = open("/tmp/list", "w")
            f.write(str(out))
            f.close()
            return out

    def filter(self, request, queryset):
            if not self.value():
                    return queryset
            else:
                    out = []
                    if self.value() == 'yes':
                            for i in queryset:
                                    try:
                                            if i.online_status() != "offline":
                                                    out.append(i)
                                    except:
                                            pass
                    elif self.value() == 'no':
                            for i in queryset:
                                    try:
                                            if i.online_status() == "offline":
                                                    out.append(i)
                                    except:
                                            pass
                    return out
class CardAdmin(admin.ModelAdmin):
    list_filter     = [ ... , OnlineFilter ]

每当我尝试设置在线过滤器时,文件/tmp/list将使用正确的卡片组填满,然后填充默认列表 - 就像过滤器被调用两次一样。我浏览器中的网址是?e=1而不是?online=yes。如果未设置过滤器,则只调用一次 - 在文件中只提供一组卡片。

顺便说一句:OnlineFilter.filter方法不在queryset方法中,只是为了让我知道代码中的内容,在最终版本中我只会将它放在一个方法中...... < / p> 这是一个错误吗?还是一个功能?难道我做错了什么?如果是这样,是什么?

1 个答案:

答案 0 :(得分:2)

如果django两次调用queryset函数,我不会感到惊讶 - 我似乎记得曾经注意过这一点。不知道为什么。关于过滤器无法正常工作的原因,django希望返回QuerySet,而不是列表。您可能能够构建一个查询来确定在线状态,但考虑到复杂性,我怀疑它将超出django ORM的权限,并且您需要恢复到原始SQL。另一种方法是创建一个主键列表,只需按那些过滤查询集,所以:

def filter(self, request, queryset):
    if not self.value():
        return queryset
    else:
        pks = []
        if self.value() == 'yes':
            for i in queryset:
                try:
                    if i.online_status() != "offline":
                        pks.append(i.pk)
                except:
                    pass
        elif self.value() == 'no':
              for i in queryset:
                  try:
                      if i.online_status() == "offline":
                          pks.append(i.pk)
                  except:
                      pass
        out = queryset.filter(pk__in=pks)
        return out