diff options
author | Evgeny Fadeev <evgeny.fadeev@gmail.com> | 2010-12-10 03:21:56 -0500 |
---|---|---|
committer | Evgeny Fadeev <evgeny.fadeev@gmail.com> | 2010-12-10 03:21:56 -0500 |
commit | 73efdec429ffa9fbf4b19d75dd719c8dbcd94d60 (patch) | |
tree | ec77d0c4be957629a4b159780e386621a667a283 | |
parent | 39309f87bb6bce560e4060be280db9eb2551ac16 (diff) | |
download | askbot-73efdec429ffa9fbf4b19d75dd719c8dbcd94d60.tar.gz askbot-73efdec429ffa9fbf4b19d75dd719c8dbcd94d60.tar.bz2 askbot-73efdec429ffa9fbf4b19d75dd719c8dbcd94d60.zip |
finished permalinks
-rw-r--r-- | askbot/exceptions.py | 9 | ||||
-rw-r--r-- | askbot/models/__init__.py | 2 | ||||
-rw-r--r-- | askbot/models/answer.py | 28 | ||||
-rw-r--r-- | askbot/models/meta.py | 21 | ||||
-rw-r--r-- | askbot/models/question.py | 16 | ||||
-rw-r--r-- | askbot/skins/default/templates/question.html | 4 | ||||
-rw-r--r-- | askbot/views/readers.py | 122 |
7 files changed, 137 insertions, 65 deletions
diff --git a/askbot/exceptions.py b/askbot/exceptions.py index ed60cc8a..a1d76a67 100644 --- a/askbot/exceptions.py +++ b/askbot/exceptions.py @@ -27,3 +27,12 @@ class EmailNotSent(exceptions.ImproperlyConfigured): """ pass +class QuestionHidden(exceptions.PermissionDenied): + """raised when user cannot see deleted question + """ + pass + +class AnswerHidden(exceptions.PermissionDenied): + """raised when user cannot see deleted answer + """ + pass diff --git a/askbot/models/__init__.py b/askbot/models/__init__.py index 722b4164..098271e0 100644 --- a/askbot/models/__init__.py +++ b/askbot/models/__init__.py @@ -348,7 +348,7 @@ def user_assert_can_see_deleted_post(self, post = None): error_message = _( 'This post has been deleted and can be seen only ' - 'by post ownwers, site administrators and moderators' + 'by post owners, site administrators and moderators' ) _assert_user_can( user = self, diff --git a/askbot/models/answer.py b/askbot/models/answer.py index b466fd2c..885b0e73 100644 --- a/askbot/models/answer.py +++ b/askbot/models/answer.py @@ -1,8 +1,11 @@ import datetime from django.db import models from django.utils.http import urlquote as django_urlquote +from django.utils.translation import ugettext as _ from django.core.urlresolvers import reverse +from django.core import exceptions as django_exceptions from django.conf import settings +from askbot import exceptions from askbot.models.base import AnonymousContent, DeletableContent from askbot.models.base import ContentRevision from askbot.models.base import parse_post_text, parse_and_save_post @@ -93,6 +96,29 @@ class Answer(content.Content, DeletableContent): parse = parse_post_text parse_and_save = parse_and_save_post + def assert_is_visible_to(self, user): + """raises QuestionHidden or AnswerHidden""" + try: + self.question.assert_is_visible_to(user) + except exceptions.QuestionHidden: + message = _( + 'Sorry, the answer you are looking for is ' + 'no longer available, because the parent ' + 'question has been removed' + ) + raise exceptions.QuestionHidden(message) + if self.deleted: + message = _( + 'Sorry, this answer has been ' + 'removed and is no longer accessible' + ) + if user.is_anonymous(): + raise exceptions.AnswerHidden(message) + try: + user.assert_can_see_deleted_post(self) + except django_exceptions.PermissionDenied: + raise exceptions.AnswerHidden(message) + def get_updated_activity_data(self, created = False): #todo: simplify this to always return latest revision for the second #part @@ -164,7 +190,7 @@ class Answer(content.Content, DeletableContent): paginated. This function returns number of the page on which the answer will be shown, using the default sort order. The result may depend on the visitor.""" - order_number = 1 + order_number = 0 for answer in answers: if self == answer: break diff --git a/askbot/models/meta.py b/askbot/models/meta.py index 59eeae0b..392cce24 100644 --- a/askbot/models/meta.py +++ b/askbot/models/meta.py @@ -2,7 +2,9 @@ import datetime from django.contrib.contenttypes.models import ContentType from django.db import models from django.utils import html as html_utils +from django.utils.translation import ugettext as _ from askbot import const +from askbot import exceptions from askbot.models import base from askbot.models.user import EmailFeedSetting @@ -99,6 +101,25 @@ class Comment(base.MetaContent, base.UserContent): parse = base.parse_post_text parse_and_save = base.parse_and_save_post + def assert_is_visible_to(self, user): + """raises QuestionHidden or AnswerHidden""" + try: + self.content_object.assert_is_visible_to(user) + except exceptions.QuestionHidden: + message = _( + 'Sorry, the comment you are looking for is no ' + 'longer accessible, because the parent question ' + 'has been removed' + ) + raise exceptions.QuestionHidden(message) + except exceptions.AnswerHidden: + message = _( + 'Sorry, the comment you are looking for is no ' + 'longer accessible, because the parent answer ' + 'has been removed' + ) + raise exceptions.AnswerHidden(message) + def get_origin_post(self): return self.content_object.get_origin_post() diff --git a/askbot/models/question.py b/askbot/models/question.py index 9afbf8e7..d8d60c6e 100644 --- a/askbot/models/question.py +++ b/askbot/models/question.py @@ -7,10 +7,12 @@ from django.db import models from django.contrib.auth.models import User from django.utils.http import urlquote as django_urlquote from django.core.urlresolvers import reverse +from django.core import exceptions as django_exceptions from django.contrib.sitemaps import ping_google from django.utils.translation import ugettext as _ import askbot import askbot.conf +from askbot import exceptions from askbot.models.tag import Tag, MarkedTag from askbot.models.base import AnonymousContent, DeletableContent, ContentRevision from askbot.models.base import parse_post_text, parse_and_save_post @@ -316,6 +318,20 @@ class Question(content.Content, DeletableContent): parse = parse_post_text parse_and_save = parse_and_save_post + def assert_is_visible_to(self, user): + """raises QuestionHidden""" + if self.deleted: + message = _( + 'Sorry, this question has been ' + 'deleted and is no longer accessible' + ) + if user.is_anonymous(): + raise exceptions.QuestionHidden(message) + try: + user.assert_can_see_deleted_post(self) + except django_exceptions.PermissionDenied: + raise exceptions.QuestionHidden(message) + def update_answer_count(self, save = True): """updates the denormalized field 'answer_count' on the question diff --git a/askbot/skins/default/templates/question.html b/askbot/skins/default/templates/question.html index 740ca999..4ba93263 100644 --- a/askbot/skins/default/templates/question.html +++ b/askbot/skins/default/templates/question.html @@ -118,7 +118,7 @@ </span> {% endif %} {% if request.user|can_delete_post(question) %}{{ pipe() }} - <a id="question-delete-link-{{question.id}}">{% trans %}delete{% endtrans %}</a> + <a id="question-delete-link-{{question.id}}">{% if question.deleted %}{% trans %}undelete{% endtrans %}{% else %}{% trans %}delete{% endtrans %}{% endif %}</a> {% endif %} </div> </div> @@ -241,7 +241,7 @@ {% set pipe=joiner('<span class="sep">|</span>') %} <span class="linksopt">{{ pipe() }} <a - href="#{{ answer.id }}" + href="{{ answer.get_absolute_url() }}" title="{% trans %}answer permanent link{% endtrans %}"> {% trans %}permanent link{% endtrans %} </a> diff --git a/askbot/views/readers.py b/askbot/views/readers.py index 317b0805..6fb2fd43 100644 --- a/askbot/views/readers.py +++ b/askbot/views/readers.py @@ -27,6 +27,7 @@ from django.core import exceptions as django_exceptions from django.contrib.humanize.templatetags import humanize import askbot +from askbot import exceptions from askbot.utils.html import sanitize_html #from lxml.html.diff import htmldiff from askbot.utils.diff import textDiff as htmldiff @@ -392,8 +393,6 @@ def question(request, id):#refactor - long subroutine. display question body, an """view that displays body of the question and all answers to it """ - question = get_object_or_404(models.Question, id=id) - #todo: fix inheritance of sort method from questions default_sort_method = request.session.get('questions_sort_method', 'votes') form = ShowQuestionForm(request.GET, default_sort_method) @@ -404,10 +403,59 @@ def question(request, id):#refactor - long subroutine. display question body, an is_permalink = form.cleaned_data['is_permalink'] answer_sort_method = form.cleaned_data['answer_sort_method'] - #redirect if slug in the url is wrong + #resolve comment and answer permalinks + #they go first because in theory both can be moved to another question + #this block "returns" show_post and assigns actual comment and answer + #to show_comment and show_answer variables + #in the case if the permalinked items or their parents are gone - redirect + #redirect also happens if id of the object's origin post != requested id + show_post = None #used for permalinks + #import pdb + #pdb.set_trace() + if show_comment is not None: + #comments + try: + show_comment = models.Comment.objects.get(id = show_comment) + if str(show_comment.get_origin_post().id) != id: + return HttpResponseRedirect(show_comment.get_absolute_url()) + show_post = show_comment.content_object + show_comment.assert_is_visible_to(request.user) + except models.Comment.DoesNotExist: + error_message = _( + 'Sorry, the comment you are looking for has been ' + 'deleted and is no longer accessible' + ) + request.user.message_set.create(message = error_message) + return HttpResponseRedirect(reverse('question', kwargs = {'id': id})) + except exceptions.AnswerHidden, error: + request.user.message_set.create(message = unicode(error)) + #use reverse function here because question is not yet loaded + return HttpResponseRedirect(reverse('question', kwargs = {'id': id})) + except exceptions.QuestionHidden, error: + request.user.message_set.create(message = unicode(error)) + return HttpResponseRedirect(reverse('index')) + + elif show_answer is not None: + #answers + try: + show_post = get_object_or_404(models.Answer, id = show_answer) + if str(show_post.question.id) != id: + return HttpResponseRedirect(show_post.get_absolute_url()) + show_post.assert_is_visible_to(request.user) + except django_exceptions.PermissionDenied, error: + request.user.message_set.create(message = unicode(error)) + return HttpResponseRedirect(reverse('question', kwargs = {'id': id})) + + #load question and maybe refuse showing deleted question try: - assert(request.path == question.get_absolute_url()) - except AssertionError: + question = get_object_or_404(models.Question, id=id) + question.assert_is_visible_to(request.user) + except exceptions.QuestionHidden, error: + request.user.message_set.create(message = unicode(error)) + return HttpResponseRedirect(reverse('index')) + + #redirect if slug in the url is wrong + if request.path != question.get_absolute_url(): logging.debug('no slug match!') question_url = '?'.join(( question.get_absolute_url(), @@ -415,19 +463,6 @@ def question(request, id):#refactor - long subroutine. display question body, an )) return HttpResponseRedirect(question_url) - #maybe refuse showing deleted question - if question.deleted: - try: - if request.user.is_anonymous(): - msg = _( - 'Sorry, this question has been ' - 'deleted and is no longer accessible' - ) - raise django_exceptions.PermissionDenied(msg) - request.user.assert_can_see_deleted_post(question) - except django_exceptions.PermissionDenied, e: - request.user.message_set.create(message = unicode(e)) - return HttpResponseRedirect(reverse('index')) logging.debug('answer_sort_method=' + unicode(answer_sort_method)) #load answers @@ -456,52 +491,17 @@ def question(request, id):#refactor - long subroutine. display question body, an else: filtered_answers.append(answer) - #modify variables to handle permalinks to comments and answers - linked_post_deleted = False - missing_answer_message = _( - 'Sorry, this answer has been ' - 'deleted and is no longer accessible' - ) - show_post = None + #resolve page number and comment number for permalinks comment_order_number = None - if show_comment is not None: - #comments - try: - show_comment = models.Comment.objects.get(id = show_comment) - if show_comment.get_origin_post() != question: - return HttpResponseRedirect(show_comment.get_absolute_url()) - show_page = show_comment.get_page_number(answers = filtered_answers) - comment_order_number = show_comment.get_order_number() - show_post = show_comment.content_object - except models.Comment.DoesNotExist: - missing_comment_message = _( - 'Sorry, the comment has been ' - 'deleted and is no longer accessible' - ) - request.user.message_set.create(message = missing_comment_message) - return HttpResponseRedirect(question.get_absolute_url()) - elif show_answer is not None: - #answers - try: - show_post = models.Answer.objects.get(id = show_answer) - if show_post.question != question: - return HttpResponseRedirect(show_post.get_absolute_url()) - if show_post.deleted: - if request.user.is_anonymous(): - linked_post_deleted = True - missing_post_message = missing_answer_message - else: - try: - request.user.assert_can_see_deleted_post(show_post) - except django_exceptions.PermissionDenied, e: - missing_post_message = unicode(e) - linked_post_deleted = True - show_page = show_post.get_page_number(answers = filtered_answers) - except models.Answer.DoesNotExist: - request.user.message_set.create(message = missing_answer_message) - return HttpResponseRedirect(question.get_absolute_url()) + if show_comment: + show_page = show_comment.get_page_number(answers = filtered_answers) + comment_order_number = show_comment.get_order_number() + elif show_answer: + show_page = show_post.get_page_number(answers = filtered_answers) objects_list = Paginator(filtered_answers, const.ANSWERS_PAGE_SIZE) + if show_page > objects_list.num_pages: + return HttpResponseRediect(question.get_absolute_url()) page_objects = objects_list.page(show_page) #count visits |