как искать по целочисленному полю в виде строки (например, приоритет) с помощью django-haystack?

У меня есть модель Ticket, которую я пытаюсь найти по атрибуту приоритета IntegerField в виде строки. Я могу заставить haystack+solr искать по целочисленному значению, но не по строке.

Я думал, вы можете сделать это с помощью функции prepare_priority в классе поискового индекса, но мне не повезло. Вот мой search_index.py:

from haystack import indexes
from helpdesk.models import Ticket

class TicketIndex(indexes.SearchIndex, indexes.Indexable):
    text = indexes.CharField(document=True, use_template=True)
    title = indexes.CharField(model_attr='title')
    priority = indexes.CharField(model_attr='priority')

    def prepare_priority(self, obj):
        priorities = {1:'critical', 2:'high', 3:'normal', 4:'low'}
        return priorities[obj.priority]

    def get_model(self):
        return Ticket

    def index_queryset(self):
        """Used when the entire index for model is updated."""
        return self.get_model().objects.all()

Вот мой шаблон ticket_text.txt:

{{ object.title }}
{{ object.priority }}
{{ object.body }}

Я что-то не понимаю или делаю что-то не так?

Спасибо.


person Tony    schedule 27.02.2012    source источник
comment
Я понял, как это сделать, добавив callable в свою модель Ticket, но до сих пор не могу понять, почему это нельзя сделать с помощью функции prepare...   -  person Tony    schedule 28.02.2012


Ответы (1)


Почему prepare_priority() "не работает"

SearchIndex используется для преобразования отдельных объектов данной модели в записи в вашем индексе Whoosh. Я назову эти записи SearchResults, так как они отображаются в оболочке. Теперь поля, которые вы определили в TicketIndex, (конечно) присутствуют в SearchResults для Tickets:

>>> from haystack.query import SearchQuerySet
>>> q = SearchQuerySet()
>>> ticket0 = q.all()[0]
>>> type(ticket0)
<class 'haystack.models.SearchResult'>
>>> hasattr(ticket0, 'text') and hasattr(ticket0, 'title') and hasattr(ticket0, 'priority')
True

Это означает, что 'priority' появляется дважды — один раз как независимое поле и один раз как часть содержимого 'text'. Независимое поле проходит через процедуру prepare_X. Текстовое поле проходит через шаблон (где object относится к исходному объекту модели, не словарю подготовленных данных).

>>> print ticket0.priority
critical
>>> print ticket0.text
OH NOES!!!!
1
There's a problem. Very problematic. Please fix at once.

Исправление

В моделях:

PRIORITIES = {1:'critical', 2:'high', 3:'normal', 4:'low'}
class Ticket(models.Model):
  ...
  priority = models.IntegerField(choices=PRIORITIES.items())

Используйте автоматически предоставленный get_priority_display в качестве model_attr:

class TicketIndex(indexes.SearchIndex):
  ...
  priority = indexes.CharField(model_attr='get_priority_display')

Используйте get_priority_display в шаблоне:

{{ object.get_priority_display }}
person Stumpy Joe Pete    schedule 24.06.2012
comment
Но я думал, что подготовка должна изменить значение поля, которое хранится в вашем индексе? В чем тогда смысл использования prepare в SearchIndex? - person Tony; 25.06.2012
comment
Это меняет его... но только в этом поле (обратите внимание выше, что ticket0.priority имеет решающее значение). Это не влияет на отрисовку шаблона, который используется для заполнения текстового поля (т. е. вместо ticket0.text используется 1). Это связано с тем, что {{ object.priority }} получает атрибут priority из исходного объекта Ticket, а не из объекта TicketIndex. При желании вы можете удалить поля title и priority из TicketIndex, и text все равно будет нормально отображаться. - person Stumpy Joe Pete; 26.06.2012
comment
Вам может быть интересно, какой, черт возьми, смысл иметь поля title и priority, если поле text — единственное, что ищется (и может быть создано просто отлично, без определения каких-либо других полей). Ответ заключается в том, что они полезны, когда вы напрямую используете SearchQuerySet API. . Это позволяет вам, скажем, ограничить результаты по дате, приоритету или чему-то еще. Кроме того, более продвинутая форма поиска, которая делает это за вас, использует это за кулисами. Таким образом, эти поля действуют имеют какое-то применение. - person Stumpy Joe Pete; 26.06.2012