Добрый день. Требуется упорядочить поисковую выдачу по дате - сначала новые, потом все более старые новости.
В Джанго есть модель Новостей:
# 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()
Published_manager описан так:
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
Шаблон templates/search/indexes/news/post_text.txt:
{{ object.title }}
{{ object.category.title }}
{{ object.text }}
{% for tag in object.tags.all %}
{{ tag.title }}
{% endfor %}
Поисковая вьюха:
# 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
Несмотря на то, что в модели новостей Post указан порядок выдачи результатов ordering = ('-date'), в результатах поиска новости выдаются в хаотичном порядке, изменение кода в поисковой вьюхе на:
def index_queryset(self, using=None):
return self.get_model().published_objects.all().order_by('-date')
также порядка выдачи новостей не изменило.