Answer the question
In order to leave comments, you need to log in
Why doesn't sorting search results work in django-haystack?
Good afternoon. It is required to sort the search results by date - first new, then all older news.
Django has a News model:
# news/models.py
class Post(ContentNode, ContentTypeBase):
title = models.CharField(max_length=255, verbose_name='Заголовок')
BLOCK_NAME_CHOICES = (
(0, u'Нет в блоках на главной странице'),
(1, u'Блок 1'),
(2, u'Блок 2'),
(3, u'Блок 3'),
)
block_name = models.IntegerField(verbose_name='Блок на главной странице', choices=BLOCK_NAME_CHOICES, default=0)
block_image = models.ImageField(upload_to='news/', verbose_name='Изображение для блока', blank=True, null=True)
block_text = models.CharField(max_length=25, verbose_name='Текст для блока (ФРИЗ)', blank=True, null=True)
block_text_2 = models.CharField(max_length=25, verbose_name='Текст 2-я строка (ФРИЗ)', blank=True, null=True)
date = models.DateField(verbose_name='Дата', db_index=True)
update_time = models.DateTimeField(verbose_name='Дата обновления', auto_now=True)
region = models.ForeignKey(Region, verbose_name='Регион', blank=True, null=True)
main_image_file = models.ImageField(upload_to='news/', verbose_name='Основное изображение', blank=True, null=True)
main_image_url = models.CharField(max_length=255, verbose_name='Ссылка на основное изображение', blank=True, null=True)
gallery = PluploadGalleryField(verbose_name='Дополнительные изображения', blank=True, null=True)
text = RichTextField(verbose_name='Текст')
no_persons = models.BooleanField(verbose_name='Нет персон', default=False)
mentioned_persons = ManyToManyFieldCheckbox(Person, verbose_name='Упоминаемые персоны', blank=True, null=True, related_name='news_mentions')
tags = ManyToManyFieldCheckbox(Tags, verbose_name='Теги', blank=True, null=True, related_name='news_set')
post_to_twitter = models.BooleanField(verbose_name='Опубликовать ссылку в Twitter', default=True)
posted_to_twitter = models.BooleanField(editable=False, default=False)
post_to_facebook = PostToFacebookModelField(verbose_name='Опубликовать ссылку в Facebook', default=True)
posted_to_facebook = models.BooleanField(editable=False, default=False)
default_template_path = 'news/post.html'
section_node_id = 7
objects = ContentTypeManager()
published_objects = ContentTypePublishedManager()
objects_with_deleted = models.Manager()
def __unicode__(self):
return self.title
def get_update_time(self):
return self.update_time
def get_block_name(self):
return self.block_name
def get_template_name(self):
if settings.IS_MOBILE:
return 'mobile/news/post.html'
else:
return super(Post, self).get_template_name()
def get_seo_title(self):
if self.meta_title:
return self.meta_title
else:
return u'{title}'.format(title=self.__unicode__())
def get_seo_description(self):
if self.meta_description:
return self.meta_description
else:
return u'{title} - смотрите на телеканале Союз.'.format(title=self.__unicode__())
def get_seo_keywords(self):
if self.meta_keywords:
return self.meta_keywords
else:
result = self.get_seo_title()
signs = ['.',',',':',';']
for sign in signs:
result = result.replace(sign, ' ')
return result
def generate_human_readable_url(self):
return clean_friendly_url('/news/' + strip_chars(self.title))
def get_gallery(self):
return self.gallery.all()
def has_video(self):
"""Возвращает True, если у новости есть видео"""
if '{flvremote}' in self.text or '{youtube}' in self.text:
return True
else:
return False
def get_main_image_url(self):
current_site = Site.objects.get_current()
if self.main_image_url:
if self.main_image_url.startswith('http://'):
return self.main_image_url
else:
return u'http://{0}{1}'.format(current_site.domain, self.main_image_url)
elif self.main_image_file:
return u'http://{0}{1}{2}'.format(current_site.domain, self.main_image_url, self.main_image_file.url)
else:
return u'http://{0}{1}'.format(current_site.domain, settings.MAIN_IMAGE_PLACEHOLDER_URL)
def get_related_news(self, limit=4, offset=0):
if limit != 0 or offset != 0:
news = Post.published_objects.filter(date=self.date).exclude(pk=self.pk)[offset:limit+offset]
else:
news = Post.published_objects.filter(date=self.date).exclude(pk=self.pk)
return news
def get_related_news_count(self):
return self.get_related_news(limit=0, offset=0).count()
class Meta:
verbose_name = 'Новость'
verbose_name_plural = 'Новости'
ordering = ('-date',)
permissions = (
('can_edit_foreign_posts', 'Может видеть и редактировать чужие записи'),
)
# news/search_indexes.py
from haystack import indexes
from news.models import Post
class NewsIndex(indexes.SearchIndex, indexes.Indexable):
text = indexes.EdgeNgramField(document=True, use_template=True)
date = indexes.DateTimeField(model_attr='date')
def get_model(self):
return Post
def index_queryset(self, using=None):
return self.get_model().published_objects.all()
class ContentTypePublishedManager(models.Manager):
def get_query_set(self):
qs = super(ContentTypePublishedManager, self).get_query_set().filter(
is_published=True, is_service=False, is_deleted=False
)
return qs
# search/views.py
from django.template import RequestContext
from django.shortcuts import render_to_response
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from search.forms import SearchForm
from soyuz_tv.utils import convert_from_en_to_ru_keyboard_layout
def search(request, node):
per_page = 20
context = RequestContext(request)
context['node'] = node
context['content_object'] = node
search_form = SearchForm(request.GET)
if search_form.is_valid():
search_term = search_form.cleaned_data['q'].replace('"', '')
context['search_term'] = search_term
search_results = search_form.search()
if not search_results.count():
# Возможно, запрос был введен в неправильной раскладке, пробуем поискать в другой раскладке
translated_query = convert_from_en_to_ru_keyboard_layout(
search_term
)
translated_query = translated_query
search_results_trans = search_form.searchqueryset.auto_query(translated_query)
if search_results_trans.count():
context['suggested_query'] = translated_query
search_results = search_results_trans
paginated_search_results = Paginator(search_results, per_page)
page = request.GET.get('page')
try:
search_results = paginated_search_results.page(page)
except PageNotAnInteger:
# If page is not an integer, deliver first page.
search_results = paginated_search_results.page(1)
except EmptyPage:
# If page is out of range (e.g. 9999), deliver last page of results.
search_results = paginated_search_results.page(paginated_search_results.num_pages)
context['search_results'] = search_results
context['paginator'] = paginated_search_results
context['pagination_url_prefix'] = request.path + '?q=' + search_form.cleaned_data['q']
template_path = node.get_template_name()
return render_to_response(template_path, context)
# search/forms.py
from haystack.forms import SearchForm as HaystackSearchForm
class SearchForm(HaystackSearchForm):
def clean_q(self):
q = self.cleaned_data.get('q')
q = q.replace('"', '')
return q
def index_queryset(self, using=None):
return self.get_model().published_objects.all().order_by('-date')
Answer the question
In order to leave comments, you need to log in
Haystack returns objects from the search index, not from the base. In the order in which they were returned by the search backend used (for example, ElasticSearch). Apply order_by
to search results. index_queryset
generally used only at the time of full indexing. Read the documentation for the packages you use, where such simple points are accurately considered.
You generally have a lot of problems with the code. For example, this is:
equivalent to:
or
Only the last two options are easier to read, and in general, it is not clear why such difficulties are needed. This is from the category instead of a = 1
writing setattr(__builtin__, 'a', 1)
.
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question