我在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>
这是一个错误吗?还是一个功能?难道我做错了什么?如果是这样,是什么?
答案 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