维持复杂过滤状态的策略?

时间:2009-08-28 23:19:05

标签: python django http

我需要维护一个过滤和排序对象的列表,最好是以通用方式,可以在多个视图中使用。这是必要的,因此我可以为用户生成next,prev链接以及其他一些非常有用的东西。

过滤器示例:

field__isnull=True
field__exact="so"
field__field__isnull=False

此外,在构建过滤的查询集之后,任何字段都可以应用排序。

我目前的解决方案是使用包含过滤器集合的FilterSpec类以及初始查询集。然后将该类序列化并传递给视图。

考虑包含25个动态过滤项目的视图。视图中的每个项目都有一个链接,可以获得项目的详细视图。对于每个链接,将附加当前列表的序列化FilterSpec对象。所以你最终得到了巨大的网址。更糟糕的是,所有25个链接都附加了相同的巨大过滤器!

另一种选择是将FilterSpec存储在会话中,但是您会遇到何时删除FilterSpec的问题。接下来,您会发现所有视图都混乱了代码,试图确定是否应删除过滤器以准备新的对象列表。

我确信这个问题之前已经解决了,所以我很想听听你们提出的其他解决方案。

2 个答案:

答案 0 :(得分:2)

您已经确定了在Web应用程序中维护用户特定状态的两个选项:将其存储在Cookie /会话中,或者在URL上传递它。我不相信有第三个“银弹”等待解决你的问题。

URL查询字符串选项的优点是可以将特定视图状态加入书签,作为电子邮件URL发送,& c。它还可以使您的视图代码更简单,但代价是一些额外的模板代码,以确保始终在链接上传递正确的查询字符串。

在某种程度上,您首选的解决方案可能取决于您想要的行为。例如,如果用户为某个项目的详细信息视图的书签(或向朋友发送电子邮件),您是否希望该URL只是引用该项目本身,或者始终携带有关该项目所列出的列表的信息的?如果是前者,则使用会话数据。如果是后者,请使用带有查询字符串的URL。

在任何一种情况下,我都相信你发现“混乱你所有观点”的代码可以被重构为优雅,干燥,并且你想要它是不可见的。装饰器和/或基于类的视图可能有所帮助。

答案 1 :(得分:1)

根据您的目的,您需要create a custom manager或添加new manager method

在此示例中,您添加了一个新管理器,用于选择标记为已发布的博文帖子,其中包含当前datetime之后的日期。

from django.db import models
from datetime import datetime

class PublishedPostManager(models.Manager):
    def get_query_set(self):
        return super(PublishedPostManager, self).get_query_set().filter(published=True, time__lt=datetime.now())

class Post(models.Model):
    title = models.CharField(max_length=128)
    body = models.TextField()
    published = models.BooleanField(default=False)
    time = models.DateTimeField()

    objects = models.Manager() # Needed to ensure that the default manager is still available
    published = PublishedPostManager()

然后,您可以使用Post.objects.all()代替Post.published.all()来获取所有记录。也可以使用常规的QuerySet方法:

Post.published.count()
Post.published.select_related().filter(spam__iexact='eggs')
# etc

当然,您仍然可以使用默认管理器:

Post.objects.all()