6

我有一个非常通用的视图/模板来显示给定模型的查询集的内容。
我在 12 个地方使用了 12 个不同的查询集,现在我想在其中集成 haystack 搜索,但我不能,因为 SearchQuerySet 与模板中的 QuerySet 不匹配。

使用我做的普通查询集

{%for obj in qs%}
    {{obj.foreign_key.name }}
{%endfor%}

使用 SearchQuerySet 我需要做

{%for obj in qs%} 
   {{obj.object.foreign_key.name}}
{%endfor%}

这基本上打破了我现在知道查询集来自哪里的通用模板和视图。

我想要一种让 searchqueryset 表现得像普通查询集的方法,我知道:

  • 我会输掉分数,虽然我会维持秩序
  • 我需要做一个 load_all() 来获取整个对象

关于如何保持模板通用但接受 SearchQuerySet 或将 SearchQuerySet 转换为 QuerySet 的任何提示?

4

4 回答 4

7

我使用了一个简洁的生成器技巧,可以避免向object模型添加方法,并让您对 DjangoQuerySet和 Haystack使用相同的模板SearchQuerySet

诀窍是将您的 SearchQuerySet 包装到生成器中。

# In your view...

def queryset_gen(search_qs):
    for item in search_qs:
        yield item.object  # This is the line that gets the model instance out of the Search object

qs = queryset_gen(sqs)

这种方法的优点是它维护 SearchQuerySet 返回的顺序并节省计算和内存,因为您不需要创建或存储列表的另一个实例。

于 2014-01-18T15:58:03.867 回答
4

在你的模型上添加一个名为 的方法object,让你的查询集表现得像 SearchQuerySet 怎么样?例如

class MyModel(models.Model):
    ...

    @property
    def object(self):
        return self
于 2012-12-05T21:35:04.327 回答
1

对于其他来这里寻找更通用的方法来处理像 QS 一样的 SQS 的人。

对于 Django Rest Framework,我需要这样的东西,所以我为 sqs -> qs 创建了以下包装器。它允许将 SQS 作为一个查询集进行处理,对迭代和切片的支持有限。

您还可以在迭代生成器函数之前调用 load_all。

class SearchQuerySetWrapper(object):
    """
    Decorates a SearchQuerySet object using a generator for efficient iteration
    """
    def __init__(self, qs):
        self.qs = qs

    def count(self):
        return self.qs.count()

    def __iter__(self):
        for result in self.qs:
            yield result.object

    def __getitem__( self, key):
        if isinstance(key, int) and (key >= 0 or key < self.count()):
            # return the object at the specified position
            return self.qs[key].object
        # Pass the slice/range on to the delegate
        return SearchQuerySetWrapper(self.qs[key])
于 2014-11-21T20:08:56.650 回答
0

你可以像这样创建一个数组:

q = request.GET['q']
    results = SearchQuerySet().auto_query(q)
    obj = []
    for r in results:
        obj.append(r.object)
    return render_to_response('template.html',
        {'obj': obj )
于 2012-12-03T04:43:09.907 回答