]> git.openstreetmap.org Git - osqa.git/commitdiff
Adds user based question listings and context sensitive rss feeds.
authorhernani <hernani@0cfe37f9-358a-4d5e-be75-b63607b5c754>
Mon, 28 Jun 2010 04:00:20 +0000 (04:00 +0000)
committerhernani <hernani@0cfe37f9-358a-4d5e-be75-b63607b5c754>
Mon, 28 Jun 2010 04:00:20 +0000 (04:00 +0000)
git-svn-id: http://svn.osqa.net/svnroot/osqa/trunk@452 0cfe37f9-358a-4d5e-be75-b63607b5c754

forum/feed.py
forum/models/user.py
forum/skins/default/templates/questions.html
forum/skins/default/templates/users/stats.html
forum/urls.py
forum/views/decorators.py
forum/views/readers.py

index e74e80e4fdafef45e27181d1935e3f75e281c13d..e00f33b923f3c1eff83420d81a228c96ee14fa1c 100644 (file)
@@ -1,28 +1,35 @@
-#!/usr/bin/env python
-#encoding:utf-8
-#-------------------------------------------------------------------------------
-# Name:        Syndication feed class for subsribtion
-# Purpose:
-#
-# Author:      Mike
-#
-# Created:     29/01/2009
-# Copyright:   (c) CNPROG.COM 2009
-# Licence:     GPL V2
-#-------------------------------------------------------------------------------
-from django.contrib.syndication.feeds import Feed, FeedDoesNotExist
+try:
+    from django.contrib.syndication.views import Feed, FeedDoesNotExist
+    old_version = False
+except:
+    from django.contrib.syndication.feeds import Feed, FeedDoesNotExist
+    old_version = True
+
 from django.utils.translation import ugettext as _
 from models import Question
 from forum import settings
-class RssLastestQuestionsFeed(Feed):
-    title = settings.APP_TITLE + _(' - ')+ _('latest questions')
-    link = settings.APP_URL #+ '/' + _('question/')
-    description = settings.APP_DESCRIPTION
-    #ttl = 10
+
+
+class RssQuestionFeed(Feed):
     copyright = settings.APP_COPYRIGHT
 
+    def __init__(self, question_list, title, description, request):
+        self._title = title
+        self._description = description
+        self._question_list = question_list
+        self._url = request.path
+
+        if old_version:
+            super(Feed, self).__init__(request, '')
+
+    def title(self):
+        return self._title
+
+    def link(self):
+        return self._url
+
     def item_link(self, item):
-        return self.link + item.get_absolute_url()
+        return item.get_absolute_url()
 
     def item_author_name(self, item):
         return item.author.username
@@ -34,10 +41,4 @@ class RssLastestQuestionsFeed(Feed):
         return item.added_at
 
     def items(self, item):
-       return Question.objects.filter_state(deleted=False).order_by('-last_activity_at')[:30]
-
-def main():
-    pass
-
-if __name__ == '__main__':
-    main()
+       return self._question_list[:30]
index a1481b3bce9b55f8d0d1a452080fbdbe336e9e39..53f90444c348314415e30b9bfc34a5a4c7f12c6b 100644 (file)
@@ -175,6 +175,18 @@ class User(BaseModel, DjangoUser):
     def get_absolute_url(self):
         return self.get_profile_url()
 
+    @models.permalink
+    def get_asked_url(self):
+        return ('user_questions', (), {'mode': _('asked-by'), 'user': self.id, 'slug': slugify(self.username)})
+
+    @models.permalink
+    def get_answered_url(self):
+        return ('user_questions', (), {'mode': _('answered-by'), 'user': self.id, 'slug': slugify(self.username)})
+
+    @models.permalink
+    def get_subscribed_url(self):
+        return ('user_questions', (), {'mode': _('subscribed-by'), 'user': self.id, 'slug': slugify(self.username)})
+
     def get_profile_link(self):
         profile_link = u'<a href="%s">%s</a>' % (self.get_profile_url(), self.username)
         return mark_safe(profile_link)
index ccd7d8303df2a1db6a5f1bf5f54281673755fe72..16ba09f26efcb4ce65eca670e1dc67702100d382 100644 (file)
@@ -14,7 +14,7 @@
 {% block content %}\r
 <div class="tabBar">\r
     {% question_list_title %}\r
-    <a style="float:left" href="{% url latest_questions_feed %}" title="{% trans "subscribe to question RSS feed" %}"><img src="{% media "media/images/feed-icon-small.png" %}" alt=""></a>\r
+    <a style="float:left" href="{{ feed_url }}" title="{% trans "subscribe to question RSS feed" %}"><img src="{% media "media/images/feed-icon-small.png" %}" alt=""></a>\r
     {% question_sort_tabs sort_context %}\r
 </div>\r
 <div id="listA">{% for question in questions %}\r
index 9f12493c8a9b680d7896999f9f48c0beeb77b886..35c344adc5bb1145a8a855858f34f6cacbd4896f 100644 (file)
@@ -6,11 +6,21 @@
 {% load humanize %}
 {% load question_list_tags %}
                {% block usercontent %}
+
+               {% declare %}
+                   question_count = questions.count()
+                   show_more_questions_link = question_count > 15
+                   questions = questions[:15]
+
+                   answer_count = answers.count()
+                   show_more_answers_link = answer_count > 30
+                   answers = answers[:30]
+               {% enddeclare %}
        
         <a name="questions"></a>
         {% spaceless %}
             <h2>
-                {% blocktrans count questions|length as counter %}
+                {% blocktrans count question_count as counter %}
                 <span class="count">1</span> Question
                 {% plural %}
                 <span class="count">{{counter}}</span> Questions
                    {% for question in questions %}
                        {% question_list_item question favorite_count=yes signature_type=badges %}
                    {% endfor %}
+            {% if show_more_questions_link %}
+                <div class="short-summary"  style="text-align: right">
+                    <a href="{{ view_user.get_asked_url }}">{% blocktrans with view_user.username as username %}View all questions by {{ username }}{% endblocktrans %}</a>
+                </div>
+            {% endif %}
                </div>
                <br clear="all"/>
         <a name="answers"></a>
         {% spaceless %}
             <h2>
-                {% blocktrans count answers|length as counter %}
+                {% blocktrans count answer_count as counter %}
                 <span class="count">1</span> Answer
                 {% plural %}
                 <span class="count">{{counter}}</span> Answers
                 </div>
             </div>
             {% endfor %}
+            {% if show_more_answers_link %}
+                <div class="short-summary"  style="text-align: right">
+                    <a href="{{ view_user.get_answered_url }}">{% blocktrans with view_user.username as username %}View all questions answered by {{ username }}{% endblocktrans %}</a>
+                </div>
+            {% endif %}
         </div>
-        <br/>
+        <br clear="all"/>
         <a name="votes"></a>
         {% spaceless %}
             <h2>
index 1d8b213e5b2f5d77ba134f3bb8170c05be71274a..c14fa92f4fb598f4362f5760f7ae70a64529db3a 100644 (file)
@@ -6,15 +6,12 @@ from django.conf.urls.defaults import *
 from django.conf import settings as djsettings
 from django.contrib import admin
 from forum import views as app
-from forum.feed import RssLastestQuestionsFeed
 from forum.sitemap import QuestionsSitemap
 from django.utils.translation import ugettext as _
 import logging
 
 admin.autodiscover()
-feeds = {
-    'rss': RssLastestQuestionsFeed
-}
+
 sitemaps = {
     'questions': QuestionsSitemap
 }
@@ -63,6 +60,9 @@ urlpatterns += patterns('',
                             name='related_questions'),
 
                         url(r'^%s%s$' % (_('questions/'), _('unanswered/')), app.readers.unanswered, name='unanswered'),
+                        url(r'^%s(?P<mode>[\w-]+)/(?P<user>\d+)/(?P<slug>.+)/$' % _('questions/'), app.readers.user_questions, name="user_questions"),
+
+
                         url(r'^%s(?P<id>\d+)/%s$' % (_('questions/'), _('edit/')), app.writers.edit_question,
                             name='edit_question'),
                         url(r'^%s(?P<id>\d+)/%s$' % (_('questions/'), _('close/')), app.commands.close,
@@ -135,8 +135,6 @@ urlpatterns += patterns('',
                         url(r'^%s(?P<id>\d+)/(?P<slug>.+)$' % _('badges/'), app.meta.badge, name='badge'),
                         # (r'^admin/doc/' % _('admin/doc'), include('django.contrib.admindocs.urls')),
                         url(r'^%s(.*)' % _('nimda/'), admin.site.root, name='osqa_admin'),
-                        url(r'^feeds/(?P<url>.*)/$', 'django.contrib.syndication.views.feed', {'feed_dict': feeds},
-                            name='feeds'),
                         url(r'^%s$' % _('upload/'), app.writers.upload, name='upload'),
                         url(r'^%s$' % _('search/'), app.readers.search, name='search'),
                         url(r'^%s$' % _('contact/'), app.meta.feedback, name='feedback'),
@@ -194,7 +192,7 @@ urlpatterns += patterns('',
                         url(r'^%s%s(?P<set_name>\w+)/$' % (_('admin/'), _('settings/')), app.admin.settings_set,
                             name="admin_set"),
 
-                        url(r'^feeds/rss/$', RssLastestQuestionsFeed, name="latest_questions_feed"),
+                        url(r'^feeds/rss/$', app.readers.feed, name="latest_questions_feed"),
 
                         url(r'^(?P<path>.+)$', app.meta.page, name="static_page")
                         )
index bae9712332e50a4dce652b0b6b1f996d54326c8f..4eb832a4ab1ea7d6e03c796bcf9d149eeaead29b 100644 (file)
@@ -13,6 +13,9 @@ def render(template=None, tab=None, tab_title='', weight=500, tabbed=True):
         def decorated(request, *args, **kwargs):\r
             context = func(request, *args, **kwargs)\r
 \r
+            if isinstance(context, HttpResponse):\r
+                return context\r
+\r
             if tab is not None:\r
                 context['tab'] = tab\r
 \r
@@ -32,6 +35,9 @@ def list(paginate, default_page_size):
         def decorated(request, *args, **kwargs):\r
             context = func(request, *args, **kwargs)\r
 \r
+            if isinstance(context, HttpResponse):\r
+                return context\r
+\r
             pagesize = request.utils.page_size(default_page_size)\r
             page = int(request.GET.get('page', 1))\r
 \r
index 3d353f184552bdbb1ef19c7702f2b5395ed5ffdc..7a73856317486c23def9391a8c6a1462815e00b9 100644 (file)
@@ -20,12 +20,14 @@ from django.utils.http import urlquote  as django_urlquote
 from django.template.defaultfilters import slugify
 from django.utils.safestring import mark_safe
 
-from forum.utils.html import sanitize_html
+from forum.utils.html import sanitize_html, hyperlink
 from forum.utils.diff import textDiff as htmldiff
 from forum.forms import *
 from forum.models import *
 from forum.forms import get_next_url
 from forum.actions import QuestionViewAction
+from forum.http_responses import HttpResponseUnauthorized
+from forum.feed import RssQuestionFeed
 import decorators
 
 # used in index page
@@ -40,12 +42,21 @@ QUESTIONS_PAGE_SIZE = 30
 # used in answers
 ANSWERS_PAGE_SIZE = 10
 
+def feed(request):
+    return RssQuestionFeed(
+                Question.objects.filter_state(deleted=False).order_by('-last_activity_at'),
+                settings.APP_TITLE + _(' - ')+ _('latest questions'),
+                settings.APP_DESCRIPTION,
+                request)(request)
+
+
 @decorators.render('index.html')
 def index(request):
     return question_list(request,
                          Question.objects.all(),
                          sort=request.utils.set_sort_method('active'),
-                         base_path=reverse('questions'))
+                         base_path=reverse('questions'),
+                         feed_url=reverse('latest_questions_feed'))
 
 @decorators.render('questions.html', 'unanswered', _('unanswered'), weight=400)
 def unanswered(request):
@@ -67,16 +78,46 @@ def tag(request, tag):
                          mark_safe(_('questions tagged <span class="tag">%(tag)s</span>') % {'tag': tag}),
                          request.utils.set_sort_method('active'),
                          None,
-                         mark_safe(_('Questions Tagged With <span class="tag">%(tag)s</span>') % {'tag': tag}),
+                         mark_safe(_('Questions Tagged With %(tag)s') % {'tag': tag}),
                          False)
 
+@decorators.render('questions.html', 'questions', tabbed=False)
+def user_questions(request, mode, user, slug):
+    user = get_object_or_404(User, id=user)
+
+    if mode == _('asked-by'):
+        questions = Question.objects.filter(author=user)
+        description = _("Questions asked by %s")
+    elif mode == _('answered-by'):
+        questions = Question.objects.filter(children__author=user, children__node_type='answer').distinct()
+        description = _("Questions answered by %s")
+    elif mode == _('subscribed-by'):
+        if not (request.user.is_superuser or request.user == user):
+            return HttpResponseUnauthorized(request)
+        questions = user.subscriptions
+
+        if request.user == user:
+            description = _("Questions you subscribed %s")
+        else:
+            description = _("Questions subscribed by %s")
+    else:
+        raise Http404
+
+
+    return question_list(request, questions,
+                         mark_safe(description % hyperlink(user.get_profile_url(), user.username)),
+                         request.utils.set_sort_method('active'),
+                         page_title=description % user.username)
+
+
 @decorators.list('questions', QUESTIONS_PAGE_SIZE)
 def question_list(request, initial,
                   list_description=_('questions'),
                   sort=None,
                   base_path=None,
                   page_title=_("All Questions"),
-                  allowIgnoreTags=True):
+                  allowIgnoreTags=True,
+                  feed_url=None):
 
     questions = initial.filter_state(deleted=False)
 
@@ -97,6 +138,9 @@ def question_list(request, initial,
     if page_title is None:
         page_title = _("Questions")
 
+    if request.GET.get('type', None) == 'rss':
+        return RssQuestionFeed(questions, page_title, list_description, request)(request)
+
     keywords =  ""
     if request.GET.get("q"):
         keywords = request.GET.get("q").strip()
@@ -104,17 +148,20 @@ def question_list(request, initial,
     answer_count = Answer.objects.filter_state(deleted=False).filter(parent__in=questions).count()
     answer_description = _("answers")
 
+    if not feed_url:
+        feed_url = request.path + "?type=rss"
+
     return {
     "questions" : questions,
     "questions_count" : questions.count(),
     "answer_count" : answer_count,
     "keywords" : keywords,
-    #"tags_autocomplete" : _get_tags_cache_json(),
     "list_description": list_description,
     "answer_description": answer_description,
     "base_path" : base_path,
     "page_title" : page_title,
     "tab" : "questions",
+    'feed_url': feed_url,
     }