我有一个非常通用的视图/模板来显示给定模型的查询集的内容。我从12个地方使用12个不同的查询集,现在我想在其中集成干草堆搜索,但是我不能,因为SearchQuerySet与模板中的QuerySet不匹配。
我使用普通的查询集
{%for obj in qs%}
{{obj.foreign_key.name }}
{%endfor%}
我需要使用SearchQuerySet
{%for obj in qs%}
{{obj.object.foreign_key.name}}
{%endfor%}
基本上打破了我的通用模板,现在知道了查询集的来源的视图。
我希望有一种方法使searchqueryset的行为像普通的queryset一样,并且我知道:
关于如何保持我的模板通用但接受SearchQuerySet或将SearchQuerySet转换为QuerySet的任何提示?
[我使用了一种简洁的生成器技巧,可以避免在模型中添加object
方法,并让您为Django的QuerySet
和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返回的顺序,并节省了计算和内存,因为您无需创建或存储列表的另一个实例。
如何在模型中添加一个名为object
的方法,以使查询集的行为类似于SearchQuerySet?例如
class MyModel(models.Model):
...
@property
def object(self):
return self
对于其他来这里寻求更一般的方法来对待像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])
您可以创建一个像这样的数组:
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 )