summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--askbot/auth.py10
-rw-r--r--askbot/const/__init__.py8
-rw-r--r--askbot/doc/source/optional-modules.rst11
-rw-r--r--askbot/models/__init__.py41
-rw-r--r--askbot/models/badges.py30
-rw-r--r--askbot/models/post.py10
-rw-r--r--askbot/models/question.py94
-rw-r--r--askbot/models/repute.py16
-rw-r--r--askbot/models/tag.py1
-rw-r--r--askbot/search/haystack/__init__.py59
-rw-r--r--askbot/setup_templates/settings.py8
-rw-r--r--askbot/setup_templates/settings.py.mustache9
-rw-r--r--askbot/startup_procedures.py20
-rw-r--r--askbot/tests/__init__.py1
-rw-r--r--askbot/tests/__init__.py.orig19
-rw-r--r--askbot/tests/badge_tests.py64
-rw-r--r--askbot/tests/db_api_tests.py10
-rw-r--r--askbot/tests/haystack_search_tests.py101
-rw-r--r--askbot/tests/post_model_tests.py6
-rw-r--r--askbot/views/commands.py7
-rw-r--r--askbot/views/users.py8
-rw-r--r--askbot/views/writers.py8
22 files changed, 383 insertions, 158 deletions
diff --git a/askbot/auth.py b/askbot/auth.py
index c80f5db1..846445b4 100644
--- a/askbot/auth.py
+++ b/askbot/auth.py
@@ -238,7 +238,7 @@ def onAnswerAcceptCanceled(answer, user, timestamp=None):
reputation.save()
if answer.author == question.author and user == question.author:
- #a symmettric measure for the reputation gaming plug
+ #a symmettric measure for the reputation gaming plug
#as in the onAnswerAccept function
#here it protects the user from uwanted reputation loss
return
@@ -263,7 +263,7 @@ def onUpVoted(vote, post, user, timestamp=None):
if post.post_type != 'comment':
post.vote_up_count = int(post.vote_up_count) + 1
- post.score = int(post.score) + 1
+ post.points = int(post.points) + 1
post.save()
if post.post_type == 'comment':
@@ -300,7 +300,7 @@ def onUpVotedCanceled(vote, post, user, timestamp=None):
if post.vote_up_count < 0:
post.vote_up_count = 0
- post.score = int(post.score) - 1
+ post.points = int(post.points) - 1
post.save()
if post.post_type == 'comment':
@@ -333,7 +333,7 @@ def onDownVoted(vote, post, user, timestamp=None):
vote.save()
post.vote_down_count = int(post.vote_down_count) + 1
- post.score = int(post.score) - 1
+ post.points = int(post.points) - 1
post.save()
if not (post.wiki or post.is_anonymous):
@@ -375,7 +375,7 @@ def onDownVotedCanceled(vote, post, user, timestamp=None):
post.vote_down_count = int(post.vote_down_count) - 1
if post.vote_down_count < 0:
post.vote_down_count = 0
- post.score = post.score + 1
+ post.points = post.points + 1
post.save()
if not (post.wiki or post.is_anonymous):
diff --git a/askbot/const/__init__.py b/askbot/const/__init__.py
index 5f47bb79..977cf0c5 100644
--- a/askbot/const/__init__.py
+++ b/askbot/const/__init__.py
@@ -299,7 +299,7 @@ POST_STATUS = {
'deleted': _('[deleted]'),
'default_version': _('initial version'),
'retagged': _('retagged'),
- 'private': _('[private]')
+ 'private': _('[private]')
}
#choices used in email and display filters
@@ -361,7 +361,7 @@ DEFAULT_USER_STATUS = 'w'
#number of items to show in user views
USER_VIEW_DATA_SIZE = 50
-#not really dependency, but external links, which it would
+#not really dependency, but external links, which it would
#be nice to test for correctness from time to time
DEPENDENCY_URLS = {
'akismet': 'https://akismet.com/signup/',
@@ -411,8 +411,8 @@ SEARCH_ORDER_BY = (
('last_activity_at', _('activity ascendant')),
('-answer_count', _('answers descendant')),
('answer_count', _('answers ascendant')),
- ('-score', _('votes descendant')),
- ('score', _('votes ascendant')),
+ ('-points', _('votes descendant')),
+ ('points', _('votes ascendant')),
)
DEFAULT_QUESTION_WIDGET_STYLE = """
diff --git a/askbot/doc/source/optional-modules.rst b/askbot/doc/source/optional-modules.rst
index 3337ef0c..aab80bf4 100644
--- a/askbot/doc/source/optional-modules.rst
+++ b/askbot/doc/source/optional-modules.rst
@@ -55,6 +55,17 @@ Finally, add lin
.. _embedding-video:
+Haystack search
+=============
+Askbot supports `Haystack <http://haystacksearch.org/>`_, a modular search framework that supports popular search engine backends as
+Solr, Elasticsearch, Whoosh and Xapian.
+
+To enable:
+
+* add 'haystack' to INSTALLED_APPS
+* add ENABLE_HAYSTACK_SEARCH = True in settings.py
+* Configure your search backend according to your setup following `this guide <http://django-haystack.readthedocs.org/en/latest/tutorial.html#modify-your-settings-py>`_
+
Embedding video
===============
diff --git a/askbot/models/__init__.py b/askbot/models/__init__.py
index 83e67bb9..ee8bbc47 100644
--- a/askbot/models/__init__.py
+++ b/askbot/models/__init__.py
@@ -93,23 +93,28 @@ def get_users_by_text_query(search_query, users_query_set = None):
"""Runs text search in user names and profile.
For postgres, search also runs against user group names.
"""
- import askbot
- if users_query_set is None:
- users_query_set = User.objects.all()
- if 'postgresql_psycopg2' in askbot.get_database_engine_name():
- from askbot.search import postgresql
- return postgresql.run_full_text_search(users_query_set, search_query)
+ if django_settings.ENABLE_HAYSTACK_SEARCH:
+ from askbot.search.haystack import AskbotSearchQuerySet
+ qs = AskbotSearchQuerySet().filter(content=search_query).models(User).get_django_queryset(User)
+ return qs
else:
- return users_query_set.filter(
- models.Q(username__icontains=search_query) |
- models.Q(about__icontains=search_query)
- )
- #if askbot.get_database_engine_name().endswith('mysql') \
- # and mysql.supports_full_text_search():
- # return User.objects.filter(
- # models.Q(username__search = search_query) |
- # models.Q(about__search = search_query)
- # )
+ import askbot
+ if users_query_set is None:
+ users_query_set = User.objects.all()
+ if 'postgresql_psycopg2' in askbot.get_database_engine_name():
+ from askbot.search import postgresql
+ return postgresql.run_full_text_search(users_query_set, search_query)
+ else:
+ return users_query_set.filter(
+ models.Q(username__icontains=search_query) |
+ models.Q(about__icontains=search_query)
+ )
+ #if askbot.get_database_engine_name().endswith('mysql') \
+ # and mysql.supports_full_text_search():
+ # return User.objects.filter(
+ # models.Q(username__search = search_query) |
+ # models.Q(about__search = search_query)
+ # )
User.add_to_class(
'status',
@@ -851,7 +856,7 @@ def user_assert_can_delete_question(self, question = None):
#if there are answers by other people,
#then deny, unless user in admin or moderator
answer_count = question.thread.all_answers()\
- .exclude(author=self).exclude(score__lte=0).count()
+ .exclude(author=self).exclude(points__lte=0).count()
if answer_count > 0:
if self.is_administrator() or self.is_moderator():
@@ -2458,7 +2463,7 @@ def _process_vote(user, post, timestamp=None, cancel=False, vote_type=None):
if post.post_type == 'question':
#denormalize the question post score on the thread
- post.thread.score = post.score
+ post.thread.points = post.points
post.thread.save()
post.thread.update_summary_html()
diff --git a/askbot/models/badges.py b/askbot/models/badges.py
index 61149df3..244c8e2f 100644
--- a/askbot/models/badges.py
+++ b/askbot/models/badges.py
@@ -43,13 +43,13 @@ class Badge(object):
"""
def __init__(self,
key = '',
- name = '',
+ name = '',
level = None,
description = None,
multiple = False):
#key - must be an ASCII only word
- self.key = key
+ self.key = key
self.name = name
self.level = level
self.description = description
@@ -114,11 +114,11 @@ class Badge(object):
def consider_award(self, actor = None,
context_object = None, timestamp = None):
- """Normally this method should be reimplemented
+ """Normally this method should be reimplemented
in subclass, but some badges are awarded without
checks. Those do no need to override this method
- actor - user who committed some action, context_object -
+ actor - user who committed some action, context_object -
the object related to the award situation, e.g. answer
"""
return self.award(actor, context_object, timestamp)
@@ -141,7 +141,7 @@ class Disciplined(Badge):
if context_object.author != actor:
return False
- if context_object.score >= \
+ if context_object.points>= \
askbot_settings.DISCIPLINED_BADGE_MIN_UPVOTES:
return self.award(actor, context_object, timestamp)
@@ -163,7 +163,7 @@ class PeerPressure(Badge):
if context_object.author != actor:
return False
- if context_object.score <= \
+ if context_object.points<= \
-1 * askbot_settings.PEER_PRESSURE_BADGE_MIN_DOWNVOTES:
return self.award(actor, context_object, timestamp)
return False
@@ -181,12 +181,12 @@ class Teacher(Badge):
multiple = False
)
- def consider_award(self, actor = None,
+ def consider_award(self, actor = None,
context_object = None, timestamp = None):
if context_object.post_type != 'answer':
return False
- if context_object.score >= askbot_settings.TEACHER_BADGE_MIN_UPVOTES:
+ if context_object.points>= askbot_settings.TEACHER_BADGE_MIN_UPVOTES:
return self.award(context_object.author, context_object, timestamp)
return False
@@ -268,7 +268,7 @@ class SelfLearner(Badge):
question = context_object.thread._question_post()
answer = context_object
- if question.author == answer.author and answer.score >= min_upvotes:
+ if question.author == answer.author and answer.points >= min_upvotes:
self.award(context_object.author, context_object, timestamp)
class QualityPost(Badge):
@@ -294,7 +294,7 @@ class QualityPost(Badge):
context_object = None, timestamp = None):
if context_object.post_type not in ('answer', 'question'):
return False
- if context_object.score >= self.min_votes:
+ if context_object.points >= self.min_votes:
return self.award(context_object.author, context_object, timestamp)
return False
@@ -485,7 +485,7 @@ class VotedAcceptedAnswer(Badge):
if context_object.post_type != 'answer':
return None
answer = context_object
- if answer.score >= self.min_votes and answer.accepted():
+ if answer.points >= self.min_votes and answer.accepted():
return self.award(answer.author, answer, timestamp)
class Enlightened(VotedAcceptedAnswer):
@@ -537,7 +537,7 @@ class Necromancer(Badge):
delta = datetime.timedelta(askbot_settings.NECROMANCER_BADGE_MIN_DELAY)
min_score = askbot_settings.NECROMANCER_BADGE_MIN_UPVOTES
if answer.added_at - question.added_at >= delta \
- and answer.score >= min_score:
+ and answer.points >= min_score:
return self.award(answer.author, answer, timestamp)
return False
@@ -723,7 +723,7 @@ class Enthusiast(Badge):
return False
class Commentator(Badge):
- """Commentator is a bronze badge that is
+ """Commentator is a bronze badge that is
awarded once when user posts a certain number of
comments"""
def __init__(self):
@@ -778,7 +778,7 @@ class Expert(Badge):
)
ORIGINAL_DATA = """
-
+
extra badges from stackexchange
* commentator - left n comments (single)
* enthusiast, fanatic - visited site n days in a row (s)
@@ -894,7 +894,7 @@ award_badges_signal = Signal(
#context_object - database object related to the event, e.g. question
@auto_now_timestamp
-def award_badges(event = None, actor = None,
+def award_badges(event = None, actor = None,
context_object = None, timestamp = None, **kwargs):
"""function that is called when signal `award_badges_signal` is sent
"""
diff --git a/askbot/models/post.py b/askbot/models/post.py
index 9984155a..609c4f9e 100644
--- a/askbot/models/post.py
+++ b/askbot/models/post.py
@@ -358,7 +358,7 @@ class Post(models.Model):
locked_by = models.ForeignKey(User, null=True, blank=True, related_name='locked_posts')
locked_at = models.DateTimeField(null=True, blank=True)
- score = models.IntegerField(default=0)
+ points = models.IntegerField(default=0, db_column='score')
vote_up_count = models.IntegerField(default=0)
vote_down_count = models.IntegerField(default=0)
@@ -389,6 +389,14 @@ class Post(models.Model):
app_label = 'askbot'
db_table = 'askbot_post'
+ #property to support legacy themes in case there are.
+ @property
+ def score(self):
+ return int(self.points)
+ @score.setter
+ def score(self, number):
+ if number:
+ self.points = int(number)
def parse_post_text(self):
"""typically post has a field to store raw source text
diff --git a/askbot/models/question.py b/askbot/models/question.py
index 5878500d..7897250b 100644
--- a/askbot/models/question.py
+++ b/askbot/models/question.py
@@ -176,28 +176,33 @@ class ThreadManager(BaseQuerySetManager):
"""returns a query set of questions,
matching the full text query
"""
- if not qs:
- qs = self.all()
-# if getattr(settings, 'USE_SPHINX_SEARCH', False):
-# matching_questions = Question.sphinx_search.query(search_query)
-# question_ids = [q.id for q in matching_questions]
-# return qs.filter(posts__post_type='question', posts__deleted=False, posts__self_question_id__in=question_ids)
- if askbot.get_database_engine_name().endswith('mysql') \
- and mysql.supports_full_text_search():
- return qs.filter(
- models.Q(title__search = search_query) |
- models.Q(tagnames__search = search_query) |
- models.Q(posts__deleted=False, posts__text__search = search_query)
- )
- elif 'postgresql_psycopg2' in askbot.get_database_engine_name():
- from askbot.search import postgresql
- return postgresql.run_full_text_search(qs, search_query)
+ if settings.ENABLE_HAYSTACK_SEARCH:
+ from askbot.search.haystack import AskbotSearchQuerySet
+ hs_qs = AskbotSearchQuerySet().filter(content=search_query)
+ return hs_qs.get_django_queryset()
else:
- return qs.filter(
- models.Q(title__icontains=search_query) |
- models.Q(tagnames__icontains=search_query) |
- models.Q(posts__deleted=False, posts__text__icontains = search_query)
- )
+ if not qs:
+ qs = self.all()
+ # if getattr(settings, 'USE_SPHINX_SEARCH', False):
+ # matching_questions = Question.sphinx_search.query(search_query)
+ # question_ids = [q.id for q in matching_questions]
+ # return qs.filter(posts__post_type='question', posts__deleted=False, posts__self_question_id__in=question_ids)
+ if askbot.get_database_engine_name().endswith('mysql') \
+ and mysql.supports_full_text_search():
+ return qs.filter(
+ models.Q(title__search = search_query) |
+ models.Q(tagnames__search = search_query) |
+ models.Q(posts__deleted=False, posts__text__search = search_query)
+ )
+ elif 'postgresql_psycopg2' in askbot.get_database_engine_name():
+ from askbot.search import postgresql
+ return postgresql.run_full_text_search(qs, search_query)
+ else:
+ return qs.filter(
+ models.Q(title__icontains=search_query) |
+ models.Q(tagnames__icontains=search_query) |
+ models.Q(posts__deleted=False, posts__text__icontains = search_query)
+ )
def run_advanced_search(self, request_user, search_state): # TODO: !! review, fix, and write tests for this
@@ -211,8 +216,8 @@ class ThreadManager(BaseQuerySetManager):
# TODO: add a possibility to see deleted questions
qs = self.filter(
- posts__post_type='question',
- posts__deleted=False
+ posts__post_type='question',
+ posts__deleted=False,
) # (***) brings `askbot_post` into the SQL query, see the ordering section below
if askbot_settings.ENABLE_CONTENT_MODERATION:
@@ -249,7 +254,7 @@ class ThreadManager(BaseQuerySetManager):
) # TODO: unify with search_state.author ?
#unified tags - is list of tags taken from the tag selection
- #plus any tags added to the query string with #tag or [tag:something]
+ #plus any tags added to the query string with #tag or [tag:something]
#syntax.
#run tag search in addition to these unified tags
meta_data = {}
@@ -271,7 +276,7 @@ class ThreadManager(BaseQuerySetManager):
existing_tags.add(tag_record.name)
except Tag.DoesNotExist:
non_existing_tags.add(tag)
-
+
meta_data['non_existing_tags'] = list(non_existing_tags)
tags = existing_tags
else:
@@ -370,13 +375,18 @@ class ThreadManager(BaseQuerySetManager):
'activity-asc': 'last_activity_at',
'answers-desc': '-answer_count',
'answers-asc': 'answer_count',
- 'votes-desc': '-score',
- 'votes-asc': 'score',
+ 'votes-desc': '-points',
+ 'votes-asc': 'points',
'relevance-desc': '-relevance', # special Postgresql-specific ordering, 'relevance' quaso-column is added by get_for_query()
}
+
orderby = QUESTION_ORDER_BY_MAP[search_state.sort]
- qs = qs.extra(order_by=[orderby])
+
+ if not (settings.ENABLE_HAYSTACK_SEARCH and orderby=='-relevance'):
+ #FIXME: this does not produces the very same results as postgres.
+ qs = qs.extra(order_by=[orderby])
+
# HACK: We add 'ordering_key' column as an alias and order by it, because when distict() is used,
# qs.extra(order_by=[orderby,]) is lost if only `orderby` column is from askbot_post!
@@ -403,7 +413,7 @@ class ThreadManager(BaseQuerySetManager):
page_questions = Post.objects.filter(
post_type='question', thread__id__in = thread_ids
).only(# pick only the used fields
- 'id', 'thread', 'score', 'is_anonymous',
+ 'id', 'thread', 'points', 'is_anonymous',
'summary', 'post_type', 'deleted'
)
page_question_map = {}
@@ -514,13 +524,23 @@ class Thread(models.Model):
answer_accepted_at = models.DateTimeField(null=True, blank=True)
added_at = models.DateTimeField(default = datetime.datetime.now)
- score = models.IntegerField(default = 0)
+ #db_column will be removed later
+ points = models.IntegerField(default = 0, db_column='score')
objects = ThreadManager()
-
+
class Meta:
app_label = 'askbot'
+ #property to support legacy themes in case there are.
+ @property
+ def score(self):
+ return int(self.points)
+ @score.setter
+ def score(self, number):
+ if number:
+ self.points = int(number)
+
def _question_post(self, refresh=False):
if refresh and hasattr(self, '_question_cache'):
delattr(self, '_question_cache')
@@ -751,7 +771,7 @@ class Thread(models.Model):
return 'thread-data-%s-%s' % (self.id, sort_method)
def invalidate_cached_post_data(self):
- """needs to be called when anything notable
+ """needs to be called when anything notable
changes in the post data - on votes, adding,
deleting, editing content"""
#we can call delete_many() here if using Django > 1.2
@@ -798,7 +818,7 @@ class Thread(models.Model):
{
'latest':'-added_at',
'oldest':'added_at',
- 'votes':'-score'
+ 'votes':'-points'
}[sort_method]
)
#1) collect question, answer and comment posts and list of post id's
@@ -852,7 +872,7 @@ class Thread(models.Model):
#todo: there may be > 1 enquirers
published_answer_ids = list()
if self.is_moderated() and user != question_post.author:
- #if moderated - then author is guaranteed to be the
+ #if moderated - then author is guaranteed to be the
#limited visibility enquirer
published_answer_ids = self.posts.get_answers(
user=question_post.author#todo: may be > 1
@@ -940,8 +960,8 @@ class Thread(models.Model):
url = question_post.get_absolute_url()
title = thread.get_title(question_post)
result.append({'url': url, 'title': title})
-
- return result
+
+ return result
def get_cached_data():
"""similar thread data will expire
@@ -986,7 +1006,7 @@ class Thread(models.Model):
return False
def add_child_posts_to_groups(self, groups):
- """adds questions and answers of the thread to
+ """adds questions and answers of the thread to
given groups, comments are taken care of implicitly
by the underlying ``Post`` methods
"""
diff --git a/askbot/models/repute.py b/askbot/models/repute.py
index 33ec3a42..a6e9d7d1 100644
--- a/askbot/models/repute.py
+++ b/askbot/models/repute.py
@@ -75,14 +75,14 @@ class Vote(models.Model):
"""
#importing locally because of circular dependency
from askbot import auth
- score_before = self.voted_post.score
+ score_before = self.voted_post.points
if self.vote > 0:
# cancel upvote
auth.onUpVotedCanceled(self, self.voted_post, self.user)
else:
# cancel downvote
auth.onDownVotedCanceled(self, self.voted_post, self.user)
- score_after = self.voted_post.score
+ score_after = self.voted_post.points
return score_after - score_before
@@ -94,7 +94,7 @@ class BadgeData(models.Model):
awarded_to = models.ManyToManyField(User, through='Award', related_name='badges')
def _get_meta_data(self):
- """retrieves badge metadata stored
+ """retrieves badge metadata stored
in a file"""
from askbot.models import badges
return badges.get_badge(self.slug)
@@ -171,9 +171,9 @@ class ReputeManager(models.Manager):
tomorrow = today + datetime.timedelta(1)
rep_types = (1,-8)
sums = self.filter(models.Q(reputation_type__in=rep_types),
- user=user,
+ user=user,
reputed_at__range=(today, tomorrow),
- ).aggregate(models.Sum('positive'), models.Sum('negative'))
+ ).aggregate(models.Sum('positive'), models.Sum('negative'))
if sums:
pos = sums['positive__sum']
neg = sums['negative__sum']
@@ -200,7 +200,7 @@ class Repute(models.Model):
#assigned_by_moderator - so that reason can be displayed
#in that case Question field will be blank
comment = models.CharField(max_length=128, null=True)
-
+
objects = ReputeManager()
def __unicode__(self):
@@ -214,7 +214,7 @@ class Repute(models.Model):
"""returns HTML snippet with a link to related question
or a text description for a the reason of the reputation change
- in the implementation description is returned only
+ in the implementation description is returned only
for Repute.reputation_type == 10 - "assigned by the moderator"
part of the purpose of this method is to hide this idiosyncracy
@@ -242,7 +242,7 @@ class Repute(models.Model):
return '<a href="%(url)s" title="%(link_title)s">%(question_title)s</a>' \
% {
- 'url': self.question.get_absolute_url(),
+ 'url': self.question.get_absolute_url(),
'question_title': escape(self.question.thread.title),
'link_title': escape(link_title)
}
diff --git a/askbot/models/tag.py b/askbot/models/tag.py
index 38555e49..647ea5cf 100644
--- a/askbot/models/tag.py
+++ b/askbot/models/tag.py
@@ -3,6 +3,7 @@ import logging
from django.db import models
from django.contrib.auth.models import User
from django.utils.translation import ugettext as _
+from django.conf import settings
from askbot.models.base import BaseQuerySetManager
from askbot import const
from askbot.conf import settings as askbot_settings
diff --git a/askbot/search/haystack/__init__.py b/askbot/search/haystack/__init__.py
new file mode 100644
index 00000000..71f04d00
--- /dev/null
+++ b/askbot/search/haystack/__init__.py
@@ -0,0 +1,59 @@
+try:
+ from haystack import indexes, site
+ from haystack.query import SearchQuerySet
+ from askbot.models import Post, Thread, User
+
+
+ class ThreadIndex(indexes.SearchIndex):
+ text = indexes.CharField(document=True, use_template=True)
+ title = indexes.CharField(model_attr='title')
+ post_text = indexes.CharField(model_attr='posts__text__search')
+
+ def index_queryset(self):
+ return Thread.objects.filter(posts__deleted=False)
+
+ def prepare(self, obj):
+ self.prepared_data = super(ThreadIndex, self).prepare(object)
+
+ self.prepared_data['tags'] = [tag.name for tag in objects.tags.all()]
+
+ class PostIndex(indexes.SearchIndex):
+ text = indexes.CharField(document=True, use_template=True)
+ post_text = indexes.CharField(model_attr='text')
+ author = indexes.CharField(model_attr='user')
+ thread_id = indexes.CharField(model_attr='thread')
+
+ def index_queryset(self):
+ return Post.objects.filter(deleted=False)
+
+ class UserIndex(indexes.SearchIndex):
+ text = indexes.CharField(document=True, use_template=True)
+
+ def index_queryset(self):
+ return User.objects.all()
+
+ site.register(Post, PostIndex)
+ site.register(Thread, ThreadIndex)
+ site.register(User, UserIndex)
+
+ class AskbotSearchQuerySet(SearchQuerySet):
+
+ def get_django_queryset(self, model_klass=Thread):
+ '''dirty hack because models() method from the
+ SearchQuerySet does not work </3'''
+ id_list = []
+ for r in self:
+ if r.model_name in ['thread','post'] \
+ and model_klass._meta.object_name.lower() == 'thread':
+ if getattr(r, 'thread_id'):
+ id_list.append(r.thread_id)
+ else:
+ id_list.append(r.pk)
+ elif r.model_name == model_klass._meta.object_name.lower():
+ #FIXME: add a highlight here?
+ id_list.append(r.pk)
+
+ return model_klass.objects.filter(id__in=set(id_list))
+
+except:
+ pass
diff --git a/askbot/setup_templates/settings.py b/askbot/setup_templates/settings.py
index 3d24fc5e..94df6f29 100644
--- a/askbot/setup_templates/settings.py
+++ b/askbot/setup_templates/settings.py
@@ -162,6 +162,7 @@ INSTALLED_APPS = (
'django.contrib.humanize',
'django.contrib.sitemaps',
#'debug_toolbar',
+ #'haystack',
'askbot',
'askbot.deps.django_authopenid',
#'askbot.importers.stackexchange', #se loader
@@ -235,6 +236,13 @@ STATICFILES_DIRS = (
RECAPTCHA_USE_SSL = True
+#HAYSTACK_SETTINGS
+ENABLE_HAYSTACK_SEARCH = False
+HAYSTACK_SITECONF = 'askbot.search.haystack'
+#more information
+#http://django-haystack.readthedocs.org/en/v1.2.7/settings.html
+HAYSTACK_SEARCH_ENGINE = 'simple'
+
TINYMCE_COMPRESSOR = True
TINYMCE_SPELLCHECKER = False
TINYMCE_JS_ROOT = os.path.join(STATIC_ROOT, 'common/media/js/tinymce/')
diff --git a/askbot/setup_templates/settings.py.mustache b/askbot/setup_templates/settings.py.mustache
index a800edec..74295513 100644
--- a/askbot/setup_templates/settings.py.mustache
+++ b/askbot/setup_templates/settings.py.mustache
@@ -161,6 +161,8 @@ INSTALLED_APPS = (
'django.contrib.humanize',
'django.contrib.sitemaps',
#'debug_toolbar',
+ #Optional, to enable haystack search
+ #'haystack',
'askbot',
'askbot.deps.django_authopenid',
#'askbot.importers.stackexchange', #se loader
@@ -236,6 +238,13 @@ STATICFILES_DIRS = (
RECAPTCHA_USE_SSL = True
+#HAYSTACK_SETTINGS
+ENABLE_HAYSTACK_SEARCH = False
+HAYSTACK_SITECONF = 'askbot.search.haystack'
+#more information
+#http://django-haystack.readthedocs.org/en/v1.2.7/settings.html
+HAYSTACK_SEARCH_ENGINE = 'simple'
+
TINYMCE_COMPRESSOR = True
TINYMCE_SPELLCHECKER = False
TINYMCE_JS_ROOT = os.path.join(STATIC_ROOT, 'common/media/js/tinymce/')
diff --git a/askbot/startup_procedures.py b/askbot/startup_procedures.py
index 736397fb..0a9e4e07 100644
--- a/askbot/startup_procedures.py
+++ b/askbot/startup_procedures.py
@@ -531,13 +531,23 @@ def test_avatar():
short_message = True
)
+def test_haystack():
+ if 'haystack' in django_settings.INSTALLED_APPS:
+ try_import('haystack', 'django-haystack', short_message = True)
+ if not hasattr(django_settings, 'HAYSTACK_SEARCH_ENGINE'):
+ message = 'Please add HAYSTACK_SEARCH_ENGINE = simple, for more info please checkout: http://django-haystack.readthedocs.org/en/v1.2.7/settings.html#haystack-search-engine'
+ raise AskbotConfigError(message)
+ if not hasattr(django_settings, 'HAYSTACK_SITECONF'):
+ message = 'Please add HAYSTACK_SITECONF = "askbot.search.haystack"'
+ raise AskbotConfigError(message)
+
def test_custom_user_profile_tab():
setting_name = 'ASKBOT_CUSTOM_USER_PROFILE_TAB'
tab_settings = getattr(django_settings, setting_name, None)
if tab_settings:
if not isinstance(tab_settings, dict):
print "Setting %s must be a dictionary!!!" % setting_name
-
+
name = tab_settings.get('NAME', None)
slug = tab_settings.get('SLUG', None)
func_name = tab_settings.get('CONTENT_GENERATOR', None)
@@ -691,6 +701,7 @@ def run_startup_tests():
test_new_skins()
test_longerusername()
test_avatar()
+ test_haystack()
settings_tester = SettingsTester({
'CACHE_MIDDLEWARE_ANONYMOUS_ONLY': {
'value': True,
@@ -720,6 +731,13 @@ def run_startup_tests():
'RECAPTCHA_USE_SSL': {
'value': True,
'message': 'Please add: RECAPTCHA_USE_SSL = True'
+ },
+ 'ENABLE_HAYSTACK_SEARCH': {
+ 'message': 'Please add: ENABLE_HAYSTACK_SEARCH = False or True according to your setup'
+ },
+ 'HAYSTACK_SITECONF': {
+ 'value': 'askbot.search.haystack',
+ 'message': 'Please add: HAYSTACK_SITECONF = "askbot.search.haystack"'
}
})
settings_tester.run()
diff --git a/askbot/tests/__init__.py b/askbot/tests/__init__.py
index b9a8cd93..59db8f67 100644
--- a/askbot/tests/__init__.py
+++ b/askbot/tests/__init__.py
@@ -14,6 +14,7 @@ from askbot.tests.markup_test import *
from askbot.tests.post_model_tests import *
from askbot.tests.thread_model_tests import *
from askbot.tests.reply_by_email_tests import *
+from askbot.tests.haystack_search_tests import *
from askbot.tests.email_parsing_tests import *
from askbot.tests.widget_tests import *
from askbot.tests.category_tree_tests import CategoryTreeTests
diff --git a/askbot/tests/__init__.py.orig b/askbot/tests/__init__.py.orig
deleted file mode 100644
index 905c90df..00000000
--- a/askbot/tests/__init__.py.orig
+++ /dev/null
@@ -1,19 +0,0 @@
-from askbot.tests.cache_tests import *
-from askbot.tests.email_alert_tests import *
-from askbot.tests.on_screen_notification_tests import *
-from askbot.tests.page_load_tests import *
-from askbot.tests.permission_assertion_tests import *
-from askbot.tests.db_api_tests import *
-from askbot.tests.skin_tests import *
-from askbot.tests.badge_tests import *
-from askbot.tests.management_command_tests import *
-from askbot.tests.search_state_tests import *
-from askbot.tests.form_tests import *
-from askbot.tests.follow_tests import *
-from askbot.tests.templatefilter_tests import *
-from askbot.tests.markup_test import *
-from askbot.tests.post_model_tests import *
-from askbot.tests.thread_model_tests import *
-from askbot.tests.reply_by_email_tests import *
-from askbot.tests.category_tree_tests import CategoryTreeTests
-from askbot.tests.user_model_tests import UserModelTests
diff --git a/askbot/tests/badge_tests.py b/askbot/tests/badge_tests.py
index 0ed4b343..c184db6f 100644
--- a/askbot/tests/badge_tests.py
+++ b/askbot/tests/badge_tests.py
@@ -24,7 +24,7 @@ class BadgeTests(AskbotTestCase):
def assert_accepted_answer_badge_works(self,
badge_key = None,
- min_score = None,
+ min_points = None,
expected_count = 1,
previous_count = 0,
trigger = None
@@ -32,7 +32,7 @@ class BadgeTests(AskbotTestCase):
assert(trigger in ('accept_best_answer', 'upvote_answer'))
question = self.post_question(user = self.u1)
answer = self.post_answer(user = self.u2, question = question)
- answer.score = min_score - 1
+ answer.points = min_points - 1
answer.save()
recipient = answer.author
@@ -47,30 +47,30 @@ class BadgeTests(AskbotTestCase):
self.u1.upvote(answer)
self.assert_have_badge(badge_key, recipient, expected_count)
- def assert_upvoted_answer_badge_works(self,
+ def assert_upvoted_answer_badge_works(self,
badge_key = None,
- min_score = None,
+ min_points = None,
multiple = False
):
"""test answer badge where answer author is the recipient
where badge award is triggered by upvotes
- * min_score - minimum # of upvotes required
+ * min_points - minimum # of upvotes required
* multiple - multiple award or not
* badge_key - key on askbot.models.badges.Badge object
"""
question = self.post_question(user = self.u1)
answer = self.post_answer(user = self.u2, question = question)
- answer.score = min_score - 1
+ answer.points = min_points - 1
answer.save()
self.u1.upvote(answer)
self.assert_have_badge(badge_key, recipient = self.u2)
self.u3.upvote(answer)
self.assert_have_badge(badge_key, recipient = self.u2, expected_count = 1)
-
+
#post another question and check that there are no new badges
question2 = self.post_question(user = self.u1)
answer2 = self.post_answer(user = self.u2, question = question2)
- answer2.score = min_score - 1
+ answer2.score = min_points - 1
answer2.save()
self.u1.upvote(answer2)
@@ -85,28 +85,28 @@ class BadgeTests(AskbotTestCase):
expected_count = expected_count
)
- def assert_upvoted_question_badge_works(self,
+ def assert_upvoted_question_badge_works(self,
badge_key = None,
- min_score = None,
+ min_points = None,
multiple = False
):
"""test question badge where question author is the recipient
where badge award is triggered by upvotes
- * min_score - minimum # of upvotes required
+ * min_points - minimum # of upvotes required
* multiple - multiple award or not
* badge_key - key on askbot.models.badges.Badge object
"""
question = self.post_question(user = self.u1)
- question.score = min_score - 1
+ question.points = min_points - 1
question.save()
self.u2.upvote(question)
self.assert_have_badge(badge_key, recipient = self.u1)
self.u3.upvote(question)
self.assert_have_badge(badge_key, recipient = self.u1, expected_count = 1)
-
+
#post another question and check that there are no new badges
question2 = self.post_question(user = self.u1)
- question2.score = min_score - 1
+ question2.points = min_points - 1
question2.save()
self.u2.upvote(question2)
@@ -123,13 +123,13 @@ class BadgeTests(AskbotTestCase):
def test_disciplined_badge(self):
question = self.post_question(user = self.u1)
- question.score = settings.DISCIPLINED_BADGE_MIN_UPVOTES
+ question.points = settings.DISCIPLINED_BADGE_MIN_UPVOTES
question.save()
self.u1.delete_question(question)
self.assert_have_badge('disciplined', recipient = self.u1)
question2 = self.post_question(user = self.u1)
- question2.score = settings.DISCIPLINED_BADGE_MIN_UPVOTES
+ question2.points = settings.DISCIPLINED_BADGE_MIN_UPVOTES
question2.save()
self.u1.delete_question(question2)
self.assert_have_badge('disciplined', recipient = self.u1, expected_count = 2)
@@ -137,7 +137,7 @@ class BadgeTests(AskbotTestCase):
def test_peer_pressure_badge(self):
question = self.post_question(user = self.u1)
answer = self.post_answer(user = self.u1, question = question)
- answer.score = -1*settings.PEER_PRESSURE_BADGE_MIN_DOWNVOTES
+ answer.points = -1*settings.PEER_PRESSURE_BADGE_MIN_DOWNVOTES
answer.save()
self.u1.delete_answer(answer)
self.assert_have_badge('peer-pressure', recipient = self.u1)
@@ -145,21 +145,21 @@ class BadgeTests(AskbotTestCase):
def test_teacher_badge(self):
self.assert_upvoted_answer_badge_works(
badge_key = 'teacher',
- min_score = settings.TEACHER_BADGE_MIN_UPVOTES,
+ min_points = settings.TEACHER_BADGE_MIN_UPVOTES,
multiple = False
)
def test_nice_answer_badge(self):
self.assert_upvoted_answer_badge_works(
badge_key = 'nice-answer',
- min_score = settings.NICE_ANSWER_BADGE_MIN_UPVOTES,
+ min_points = settings.NICE_ANSWER_BADGE_MIN_UPVOTES,
multiple = True
)
def test_nice_question_badge(self):
self.assert_upvoted_question_badge_works(
badge_key = 'nice-question',
- min_score = settings.NICE_QUESTION_BADGE_MIN_UPVOTES,
+ min_points = settings.NICE_QUESTION_BADGE_MIN_UPVOTES,
multiple = True
)
@@ -227,7 +227,7 @@ class BadgeTests(AskbotTestCase):
question = self.post_question(user = self.u1)
answer = self.post_answer(user = self.u1, question = question)
min_votes = settings.SELF_LEARNER_BADGE_MIN_UPVOTES
- answer.score = min_votes - 1
+ answer.points = min_votes - 1
answer.save()
self.u2.upvote(answer)
self.assert_have_badge('self-learner', recipient = self.u1)
@@ -235,14 +235,14 @@ class BadgeTests(AskbotTestCase):
#copy-paste of the first question, except expect second badge
question = self.post_question(user = self.u1)
answer = self.post_answer(user = self.u1, question = question)
- answer.score = min_votes - 1
+ answer.points = min_votes - 1
answer.save()
self.u2.upvote(answer)
self.assert_have_badge('self-learner', recipient = self.u1, expected_count = 2)
question = self.post_question(user = self.u2)
answer = self.post_answer(user = self.u1, question = question)
- answer.score = min_votes - 1
+ answer.points = min_votes - 1
answer.save()
self.u2.upvote(answer)
#no badge when asker != answerer
@@ -282,13 +282,13 @@ class BadgeTests(AskbotTestCase):
def assert_enlightened_badge_works(self, trigger):
self.assert_accepted_answer_badge_works(
'enlightened',
- min_score = settings.ENLIGHTENED_BADGE_MIN_UPVOTES,
+ min_points = settings.ENLIGHTENED_BADGE_MIN_UPVOTES,
expected_count = 1,
trigger = trigger
)
self.assert_accepted_answer_badge_works(
'enlightened',
- min_score = settings.ENLIGHTENED_BADGE_MIN_UPVOTES,
+ min_points = settings.ENLIGHTENED_BADGE_MIN_UPVOTES,
expected_count = 1,
previous_count = 1,
trigger = trigger
@@ -297,13 +297,13 @@ class BadgeTests(AskbotTestCase):
def assert_guru_badge_works(self, trigger):
self.assert_accepted_answer_badge_works(
'guru',
- min_score = settings.GURU_BADGE_MIN_UPVOTES,
+ min_points = settings.GURU_BADGE_MIN_UPVOTES,
expected_count = 1,
trigger = trigger
)
self.assert_accepted_answer_badge_works(
'guru',
- min_score = settings.GURU_BADGE_MIN_UPVOTES,
+ min_points = settings.GURU_BADGE_MIN_UPVOTES,
previous_count = 1,
expected_count = 2,
trigger = trigger
@@ -330,8 +330,8 @@ class BadgeTests(AskbotTestCase):
user = self.u2,
question = question,
timestamp = future
- )
- answer.score = settings.NECROMANCER_BADGE_MIN_UPVOTES - 1
+ )
+ answer.points = settings.NECROMANCER_BADGE_MIN_UPVOTES - 1
answer.save()
self.assert_have_badge('necromancer', self.u2, expected_count = 0)
self.u1.upvote(answer)
@@ -457,7 +457,7 @@ class BadgeTests(AskbotTestCase):
self.u1.toggle_favorite_question(question)
"""no gaming"""
self.assert_have_badge('stellar-question', self.u1, 0)
-
+
def test_stellar_badge3(self):
question = self.post_question(user = self.u1)
settings.update('STELLAR_QUESTION_BADGE_MIN_STARS', 2)
@@ -480,9 +480,9 @@ class BadgeTests(AskbotTestCase):
self.post_comment(user = self.u1, parent_post = question)
self.assert_have_badge('commentator', self.u1, 0)
- self.post_comment(user = self.u1, parent_post = question)
+ self.post_comment(user = self.u1, parent_post = question)
self.assert_have_badge('commentator', self.u1, 1)
- self.post_comment(user = self.u1, parent_post = question)
+ self.post_comment(user = self.u1, parent_post = question)
self.assert_have_badge('commentator', self.u1, 1)
def test_taxonomist_badge(self):
diff --git a/askbot/tests/db_api_tests.py b/askbot/tests/db_api_tests.py
index 5ad26e8a..b9e8f5b9 100644
--- a/askbot/tests/db_api_tests.py
+++ b/askbot/tests/db_api_tests.py
@@ -173,13 +173,13 @@ class DBApiTests(AskbotTestCase):
count = models.Tag.objects.filter(name='one-tag').count()
self.assertEquals(count, 0)
-
+
@with_settings(MAX_TAG_LENGTH=200, MAX_TAGS_PER_POST=50)
def test_retag_tags_too_long_raises(self):
tags = "aoaoesuouooeueooeuoaeuoeou aostoeuoaethoeastn oasoeoa nuhoasut oaeeots aoshootuheotuoehao asaoetoeatuoasu o aoeuethut aoaoe uou uoetu uouuou ao aouosutoeh"
question = self.post_question(user=self.user)
self.assertRaises(
- exceptions.ValidationError,
+ exceptions.ValidationError,
self.user.retag_question,
question=question, tags=tags
)
@@ -415,10 +415,10 @@ class CommentTests(AskbotTestCase):
def test_other_user_can_cancel_upvote(self):
self.test_other_user_can_upvote_comment()
comment = models.Post.objects.get_comments().get(id = self.comment.id)
- self.assertEquals(comment.score, 1)
+ self.assertEquals(comment.points, 1)
self.other_user.upvote(comment, cancel = True)
comment = models.Post.objects.get_comments().get(id = self.comment.id)
- self.assertEquals(comment.score, 0)
+ self.assertEquals(comment.points, 0)
class GroupTests(AskbotTestCase):
def setUp(self):
@@ -526,7 +526,7 @@ class GroupTests(AskbotTestCase):
#because answer groups always inherit thread groups
self.edit_answer(user=self.u1, answer=answer, is_private=True)
self.assertEqual(answer.groups.count(), 1)
-
+
#here we have a simple case - the comment to answer was posted
#by the answer author!!!
#won't work when comment was by someone else
diff --git a/askbot/tests/haystack_search_tests.py b/askbot/tests/haystack_search_tests.py
new file mode 100644
index 00000000..d1592f42
--- /dev/null
+++ b/askbot/tests/haystack_search_tests.py
@@ -0,0 +1,101 @@
+"""Tests haystack indexes and queries"""
+from django.core import exceptions
+from django.conf import settings
+from django.contrib.auth.models import User
+from askbot.tests.utils import AskbotTestCase, skipIf
+from askbot import models
+import datetime
+
+class HaystackSearchTests(AskbotTestCase):
+ """tests methods on User object,
+ that were added for askbot
+ """
+ def setUp(self):
+ self._old_value = settings.ENABLE_HAYSTACK_SEARCH
+ setattr(settings, "ENABLE_HAYSTACK_SEARCH", True)
+
+ self.user = self.create_user(username='gepeto')
+ self.other_user = self.create_user(username = 'pinocho')
+ self.other_user.location = 'Managua'
+ self.other_user.about = "I'm made of wood, gepeto made me"
+ self.other_user.save()
+ body_1 = '''Lorem turpis purus? Amet mattis eu et sociis phasellus
+ montes elementum proin ut urna enim, velit, tincidunt quis ut,
+ et integer mus? Nunc! Vut sed? Ac tincidunt egestas adipiscing,
+ magna et pulvinar mid est urna ultricies, turpis tristique nisi,
+ cum. Urna. Purus elit porttitor nisi porttitor ridiculus tincidunt
+ amet duis, gepeto'''
+ #from Baldy of Nome by Esther Birdsall Darling
+ body_2 = ''' With unseeing eyes and dragging steps, the boy trudged along the snowy
+ trail, dreading the arrival at Golconda Camp. For there was the House of
+ Judgment, where all of the unfortunate events of that most unhappy day
+ would be reviewed sternly, lorem'''
+ self.question1 = self.post_question(
+ user=self.user,
+ body_text=body_1,
+ title='Test title 1'
+ )
+ self.question2 = self.post_question(
+ user=self.other_user,
+ body_text=body_2,
+ title='Test title 2, Baldy of Nome'
+ )
+ self.answer1 = self.post_answer(
+ user=self.user,
+ question = self.question1,
+ body_text="This is a answer for question 1"
+ )
+ self.answer1 = self.post_answer(
+ user=self.other_user,
+ question = self.question2,
+ body_text="Just a random text to fill the space"
+ )
+
+ def tearDown(self):
+ setattr(settings, "ENABLE_HAYSTACK_SEARCH", self._old_value)
+
+ @skipIf('haystack' not in settings.INSTALLED_APPS,
+ 'Haystack not setup')
+ def test_title_search(self):
+ #title search
+ title_search_qs = models.Thread.objects.get_for_query('title')
+ title_search_qs_2 = models.Thread.objects.get_for_query('Nome')
+ self.assertEquals(title_search_qs.count(), 2)
+ self.assertEquals(title_search_qs_2.count(), 1)
+
+ @skipIf('haystack' not in settings.INSTALLED_APPS,
+ 'Haystack not setup')
+ def test_body_search(self):
+
+ #bodysearch
+ body_search_qs = models.Thread.objects.get_for_query('Lorem')
+ self.assertEquals(body_search_qs.count(), 2)
+ body_search_qs_2 = models.Thread.objects.get_for_query('steps')
+ self.assertEquals(body_search_qs_2.count(), 1)
+
+ @skipIf('haystack' not in settings.INSTALLED_APPS,
+ 'Haystack not setup')
+ def test_user_profile_search(self):
+ #must return pinocho
+ user_profile_qs = models.get_users_by_text_query('wood')
+ self.assertEquals(user_profile_qs.count(), 1)
+
+ #returns both gepeto and pinocho because gepeto nickname
+ #and gepeto name in pinocho's profile
+ user_profile_qs = models.get_users_by_text_query('gepeto')
+ self.assertEquals(user_profile_qs.count(), 2)
+
+ @skipIf('haystack' not in settings.INSTALLED_APPS,
+ 'Haystack not setup')
+ def test_get_django_queryset(self):
+ '''makes a query that can return multiple models and test
+ get_django_queryset() method from AskbotSearchQuerySet'''
+ #gepeto is present in profile and in question
+ from askbot.search.haystack import AskbotSearchQuerySet
+ qs = AskbotSearchQuerySet().filter(content='gepeto').get_django_queryset(User)
+ for instance in qs:
+ self.assertTrue(isinstance(instance, User))
+
+ qs = AskbotSearchQuerySet().filter(content='gepeto').get_django_queryset(models.Thread)
+ for instance in qs:
+ self.assertTrue(isinstance(instance, models.Thread))
diff --git a/askbot/tests/post_model_tests.py b/askbot/tests/post_model_tests.py
index 1a3a9c49..e61fcd2d 100644
--- a/askbot/tests/post_model_tests.py
+++ b/askbot/tests/post_model_tests.py
@@ -618,7 +618,7 @@ class ThreadRenderCacheUpdateTests(AskbotTestCase):
def test_question_upvote_downvote(self):
question = self.post_question()
- question.score = 5
+ question.points = 5
question.vote_up_count = 7
question.vote_down_count = 2
question.save()
@@ -631,7 +631,7 @@ class ThreadRenderCacheUpdateTests(AskbotTestCase):
data = simplejson.loads(response.content)
self.assertEqual(1, data['success'])
- self.assertEqual(6, data['count']) # 6 == question.score(5) + 1
+ self.assertEqual(6, data['count']) # 6 == question.points(5) + 1
thread = Thread.objects.get(id=question.thread.id)
@@ -647,7 +647,7 @@ class ThreadRenderCacheUpdateTests(AskbotTestCase):
data = simplejson.loads(response.content)
self.assertEqual(1, data['success'])
- self.assertEqual(5, data['count']) # 6 == question.score(6) - 1
+ self.assertEqual(5, data['count']) # 6 == question.points(6) - 1
thread = Thread.objects.get(id=question.thread.id)
diff --git a/askbot/views/commands.py b/askbot/views/commands.py
index f02061cd..f7d22f48 100644
--- a/askbot/views/commands.py
+++ b/askbot/views/commands.py
@@ -169,7 +169,7 @@ def process_vote(user = None, vote_direction = None, post = None):
if vote != None:
user.assert_can_revoke_old_vote(vote)
score_delta = vote.cancel()
- response_data['count'] = post.score + score_delta
+ response_data['count'] = post.points+ score_delta
response_data['status'] = 1 #this means "cancel"
else:
@@ -192,7 +192,7 @@ def process_vote(user = None, vote_direction = None, post = None):
else:
vote = user.downvote(post = post)
- response_data['count'] = post.score
+ response_data['count'] = post.points
response_data['status'] = 0 #this means "not cancel", normal operation
response_data['success'] = 1
@@ -842,7 +842,8 @@ def upvote_comment(request):
)
else:
raise ValueError
- return {'score': comment.score}
+ #FIXME: rename js
+ return {'score': comment.points}
@csrf.csrf_exempt
@decorators.ajax_only
diff --git a/askbot/views/users.py b/askbot/views/users.py
index 65862697..707f4e14 100644
--- a/askbot/views/users.py
+++ b/askbot/views/users.py
@@ -372,7 +372,7 @@ def user_stats(request, user, context):
# Questions
#
questions = user.posts.get_questions().filter(**question_filter).\
- order_by('-score', '-thread__last_activity_at').\
+ order_by('-points', '-thread__last_activity_at').\
select_related('thread', 'thread__last_activity_by')[:100]
#added this if to avoid another query if questions is less than 100
@@ -393,7 +393,7 @@ def user_stats(request, user, context):
).select_related(
'thread'
).order_by(
- '-score', '-added_at'
+ '-points', '-added_at'
)[:100]
top_answer_count = len(top_answers)
@@ -726,7 +726,7 @@ def user_responses(request, user, context):
and "flags" - moderation items for mods only
"""
- #0) temporary, till urls are fixed: update context
+ #0) temporary, till urls are fixed: update context
# to contain response counts for all sub-sections
context.update(view_context.get_for_inbox(request.user))
@@ -906,7 +906,7 @@ def user_favorites(request, user, context):
favorite_threads = user.user_favorite_questions.values_list('thread', flat=True)
questions = models.Post.objects.filter(post_type='question', thread__in=favorite_threads)\
.select_related('thread', 'thread__last_activity_by')\
- .order_by('-score', '-thread__last_activity_at')[:const.USER_VIEW_DATA_SIZE]
+ .order_by('-points', '-thread__last_activity_at')[:const.USER_VIEW_DATA_SIZE]
data = {
'active_tab':'users',
diff --git a/askbot/views/writers.py b/askbot/views/writers.py
index 4024b4b0..8fcea796 100644
--- a/askbot/views/writers.py
+++ b/askbot/views/writers.py
@@ -473,7 +473,7 @@ def edit_answer(request, id):
if request.POST['select_revision'] == 'true':
# user has changed revistion number
revision_form = forms.RevisionForm(
- answer,
+ answer,
revision,
request.POST
)
@@ -618,7 +618,8 @@ def __generate_comments_json(obj, user):#non-view generates json data for the po
'user_id': comment_owner.id,
'is_deletable': is_deletable,
'is_editable': is_editable,
- 'score': comment.score,
+ 'points': comment.points,
+ 'score': comment.points, #to support js
'upvoted_by_user': getattr(comment, 'upvoted_by_user', False)
}
json_comments.append(comment_data)
@@ -685,7 +686,8 @@ def edit_comment(request):
'user_id': comment_post.author.id,
'is_deletable': is_deletable,
'is_editable': is_editable,
- 'score': comment_post.score,
+ 'score': comment_post.points, #to support unchanged js
+ 'points': comment_post.points,
'voted': comment_post.is_upvoted_by(request.user),
}