* Bugfix for double results in "show own posts" * Don't put user_id in GET -> use request.user * remove {% if results %} with {% for %}...{% empty %} * Refactor search()

Fixed topic search results which returned nothing.
Return a list instead of a generator in TopicFromPostResult.__getitem__() so that the pagination can work correctly.
from: https://bitbucket.org/hsoft/djangobb/changeset/1b2f31c54c516c699a7b11a1d43b170742157df5

use the slow, but correct solution for display the result as topics

used fast solution with a work-a-round for double topics

respect sort order

count only one time

better solution, but slow with woosh and many hits

change info

make it DRY

remove debug imports

remove not needed tuple()

* add "show your topics/posts" search
* add link to switch between topics/posts search
* merge {% block controls %}
* make search_posts.html useable with queryset and SearchQuerySet

Add topic <-> post switch links to other type of search, too.

not really in GET needed.

* Use PostSearchForm() in normal search
* add switch links to normal search, too.

better docstring

better text?
This commit is contained in:
JensDiemer 2012-08-08 11:00:28 +03:00
parent c566df87ed
commit 48ed192424
8 changed files with 222 additions and 188 deletions
djangobb_forum

View file

@ -14,20 +14,20 @@ from django.db import transaction
from django.views.decorators.csrf import csrf_exempt
from django.utils.translation import ugettext as _
from djangobb_forum.util import build_form, paginate, set_language
from djangobb_forum.models import Category, Forum, Topic, Post, Profile, Reputation, \
Attachment, PostTracking
from djangobb_forum import settings as forum_settings
from djangobb_forum.forms import AddPostForm, EditPostForm, UserSearchForm, \
PostSearchForm, ReputationForm, MailToForm, EssentialsProfileForm, \
PersonalProfileForm, MessagingProfileForm, PersonalityProfileForm, \
DisplayProfileForm, PrivacyProfileForm, ReportForm, UploadAvatarForm
from djangobb_forum.models import Category, Forum, Topic, Post, Profile, Reputation, \
Attachment, PostTracking
from djangobb_forum.templatetags import forum_extras
from djangobb_forum import settings as forum_settings
from djangobb_forum.util import smiles, convert_text_to_html, TopicFromPostResult
from djangobb_forum.templatetags.forum_extras import forum_moderated_by
from djangobb_forum.util import build_form, paginate, set_language, smiles, convert_text_to_html
from haystack.query import SearchQuerySet, SQ
from django.contrib import messages
from django.core.exceptions import SuspiciousOperation
def index(request, full=True):
@ -110,91 +110,145 @@ def moderate(request, forum_id):
def search(request):
# TODO: move to form
if 'action' in request.GET:
action = request.GET['action']
#FIXME: show_user for anonymous raise exception,
#django bug http://code.djangoproject.com/changeset/14087 :|
groups = request.user.groups.all() or [] #removed after django > 1.2.3 release
topics = Topic.objects.filter(
Q(forum__category__groups__in=groups) | \
Q(forum__category__groups__isnull=True))
if action == 'show_24h':
date = datetime.today() - timedelta(1)
topics = topics.filter(created__gte=date)
elif action == 'show_new':
try:
last_read = PostTracking.objects.get(user=request.user).last_read
except PostTracking.DoesNotExist:
last_read = None
if last_read:
topics = topics.filter(last_post__updated__gte=last_read).all()
else:
#searching more than forum_settings.SEARCH_PAGE_SIZE in this way - not good idea :]
topics = [topic for topic in topics[:forum_settings.SEARCH_PAGE_SIZE] if forum_extras.has_unreads(topic, request.user)]
elif action == 'show_unanswered':
topics = topics.filter(post_count=1)
elif action == 'show_subscriptions':
topics = topics.filter(subscribers__id=request.user.id)
elif action == 'show_user':
user_id = request.GET['user_id']
posts = Post.objects.filter(user__id=user_id)
topics = [post.topic for post in posts if post.topic in topics]
elif action == 'search':
keywords = request.GET.get('keywords')
author = request.GET.get('author')
forum = request.GET.get('forum')
search_in = request.GET.get('search_in')
sort_by = request.GET.get('sort_by')
sort_dir = request.GET.get('sort_dir')
# TODO: used forms in every search type
if not (keywords or author):
return HttpResponseRedirect(reverse('djangobb:search'))
query = SearchQuerySet().models(Post)
if author:
query = query.filter(author__username=author)
if forum != u'0':
query = query.filter(forum__id=forum)
if keywords:
if search_in == 'all':
query = query.filter(SQ(topic=keywords) | SQ(text=keywords))
elif search_in == 'message':
query = query.filter(text=keywords)
elif search_in == 'topic':
query = query.filter(topic=keywords)
# add exlusions for categories user does not have access too
for category in Category.objects.all():
if not category.has_access(request.user):
query = query.exclude(category=category)
order = {'0': 'created',
'1': 'author',
'2': 'topic',
'3': 'forum'}.get(sort_by, 'created')
if sort_dir == 'DESC':
order = '-' + order
posts = query.order_by(order)
if 'topics' in request.GET['show_as']:
return render(request, 'djangobb_forum/search_topics.html', {
'results': TopicFromPostResult(posts)
})
elif 'posts' in request.GET['show_as']:
return render(request, 'djangobb_forum/search_posts.html', {'results': posts})
return render(request, 'djangobb_forum/search_topics.html', {'results': topics})
else:
form = PostSearchForm()
def _render_search_form(form=None):
return render(request, 'djangobb_forum/search_form.html', {'categories': Category.objects.all(),
'form': form,
})
if not 'action' in request.GET:
return _render_search_form(form=PostSearchForm())
if request.GET.get("show_as") == "posts":
show_as_posts = True
template_name = 'djangobb_forum/search_posts.html'
else:
show_as_posts = False
template_name = 'djangobb_forum/search_topics.html'
context = {}
#FIXME: show_user for anonymous raise exception,
#django bug http://code.djangoproject.com/changeset/14087 :|
groups = request.user.groups.all() or [] #removed after django > 1.2.3 release
topics = Topic.objects.filter(
Q(forum__category__groups__in=groups) | \
Q(forum__category__groups__isnull=True))
base_url = None
_generic_context = True
action = request.GET['action']
if action == 'show_24h':
date = datetime.today() - timedelta(1)
topics = topics.filter(created__gte=date)
elif action == 'show_new':
try:
last_read = PostTracking.objects.get(user=request.user).last_read
except PostTracking.DoesNotExist:
last_read = None
if last_read:
topics = topics.filter(last_post__updated__gte=last_read).all()
else:
#searching more than forum_settings.SEARCH_PAGE_SIZE in this way - not good idea :]
topics = [topic for topic in topics[:forum_settings.SEARCH_PAGE_SIZE] if forum_extras.has_unreads(topic, request.user)]
elif action == 'show_unanswered':
topics = topics.filter(post_count=1)
elif action == 'show_subscriptions':
topics = topics.filter(subscribers__id=request.user.id)
elif action == 'show_user':
# Show all posts from user or topics started by user
user_id = request.GET.get("user_id", request.user.id)
user_id = int(user_id)
posts = Post.objects.filter(user__id=user_id)
base_url = "?action=show_user&user_id=%s&show_as=" % user_id
if not show_as_posts:
# show as topic
# FIXME: This should be speed up. This is not lazy:
user_topics = []
for post in posts:
topic = post.topic
if topic in topics and topic not in user_topics:
user_topics.append(topic)
topics = user_topics
elif action == 'search':
form = PostSearchForm(request.GET)
if not form.is_valid():
return _render_search_form(form)
keywords = form.cleaned_data['keywords']
author = form.cleaned_data['author']
forum = form.cleaned_data['forum']
search_in = form.cleaned_data['search_in']
sort_by = form.cleaned_data['sort_by']
sort_dir = form.cleaned_data['sort_dir']
query = SearchQuerySet().models(Post)
if author:
query = query.filter(author__username=author)
if forum != u'0':
query = query.filter(forum__id=forum)
if keywords:
if search_in == 'all':
query = query.filter(SQ(topic=keywords) | SQ(text=keywords))
elif search_in == 'message':
query = query.filter(text=keywords)
elif search_in == 'topic':
query = query.filter(topic=keywords)
# add exlusions for categories user does not have access too
for category in Category.objects.all():
if not category.has_access(request.user):
query = query.exclude(category=category)
order = {'0': 'created',
'1': 'author',
'2': 'topic',
'3': 'forum'}.get(sort_by, 'created')
if sort_dir == 'DESC':
order = '-' + order
posts = query.order_by(order)
if not show_as_posts:
# TODO: We have here a problem to get a list of topics without double entries.
# Maybe we must add a search index over topics?
# Info: If whoosh backend used, setup HAYSTACK_ITERATOR_LOAD_PER_QUERY
# to a higher number to speed up
post_pks = posts.values_list("pk", flat=True)
context["topics"] = Topic.objects.filter(posts__in=post_pks).distinct()
else:
context["posts"] = posts
get_query_dict = request.GET.copy()
get_query_dict.pop("show_as")
base_url = "?%s&show_as=" % get_query_dict.urlencode()
_generic_context = False
if _generic_context:
if show_as_posts:
context["posts"] = Post.objects.filter(topic__in=topics).order_by('-created')
else:
context["topics"] = topics
if base_url is None:
base_url = "?action=%s&show_as=" % action
if show_as_posts:
context["as_topic_url"] = base_url + "topics"
else:
context["as_post_url"] = base_url + "posts"
return render(request, template_name, context)
@login_required
def misc(request):