damned-lies r1463 - in trunk: . common feeds media/img templates/feeds templates/languages templates/teams vertimus



Author: stephaner
Date: Wed Mar  4 15:33:15 2009
New Revision: 1463
URL: http://svn.gnome.org/viewvc/damned-lies?rev=1463&view=rev

Log:
2009-03-04  StÃphane Raimbault  <stephane raimbault gmail com>

	New RSS feeds to follow the Vertimus actions by team or
	language (#566504).

	* common/utils.py: Add a function to merge and sort two list of
	objects.
	* feeds/urls.py: Feed urls.
	* settings_sample.py: Add the feed application.
	* templates/feeds/actions_description.html: Feed item content.
	* templates/feeds/actions_title.html: Feed item title.
	* templates/languages/language_list.html: Add an RSS icon to each
	languages.	
	* templates/teams/team_detail.html: Associate the feed to the page.
	* media/img/feed-icon-10x10.png: Added feed icon.
	* urls.py: Add the '/rss' path.
	* vertimus/feeds.py: Generate the content of the Vertimus feeds.
	* vertimus/models.py: Add __unicode__ function to the archived actions.


Added:
   trunk/feeds/
   trunk/feeds/__init__.py
   trunk/feeds/urls.py
   trunk/media/img/feed-icon-10x10.png   (contents, props changed)
   trunk/templates/feeds/
   trunk/templates/feeds/actions_description.html   (contents, props changed)
   trunk/templates/feeds/actions_title.html   (contents, props changed)
   trunk/vertimus/feeds.py
Modified:
   trunk/ChangeLog
   trunk/common/utils.py
   trunk/settings_sample.py
   trunk/templates/languages/language_list.html
   trunk/templates/teams/team_detail.html
   trunk/urls.py
   trunk/vertimus/models.py

Modified: trunk/common/utils.py
==============================================================================
--- trunk/common/utils.py	(original)
+++ trunk/common/utils.py	Wed Mar  4 15:33:15 2009
@@ -22,9 +22,51 @@
 from django.utils.translation import ugettext as _
 
 def trans_sort_object_list(lst, tr_field):
-    """ Sort an object list with translated_name """
+    """Sort an object list with translated_name"""
     for l in lst:
         l.translated_name = _(getattr(l, tr_field))
     templist = [(obj_.translated_name.lower(), obj_) for obj_ in lst]
     templist.sort()
     return [obj_ for (key1, obj_) in templist]
+
+def merge_sorted_by_field(object_list1, object_list2, field):
+    """
+    Each call returns the next item, sorted by field in ascending order or in
+    descending order if the field name begins by a minus sign.
+
+    The lists of objects must be already sorted in the same order as field.
+
+    >>> from datetime import datetime
+    >>> import itertools
+    >>> class Foo(object):
+    ...     def __init__(self, num):
+    ...         self.num = num
+    ...     def __repr__(self):
+    ...         return str(self.num)
+    ...
+    >>> l1 = (Foo(1), Foo(4), Foo(5))
+    >>> l2 = (Foo(1), Foo(2), Foo(4), Foo(4), Foo(6))
+    >>> merge_sorted_by_field(l1, l2, 'num')
+    [1, 1, 2, 4, 4, 4, 5, 6]
+    >>> merge_sorted_by_field(l1, l2, 'num')[:3]
+    [1, 1, 2]
+    >>> l1 = (Foo(5), Foo(4), Foo(1))
+    >>> l2 = (Foo(6), Foo(4), Foo(4), Foo(2), Foo(1))
+    >>> [el.num for el in merge_sorted_by_field(l1, l2, '-num')]
+    [6, 5, 4, 4, 4, 2, 1, 1]
+    """
+    import itertools
+    if field is not None and field[0] == '-':
+        # Reverse the sort order
+        field = field[1:]
+        reverse = True
+    else:
+        reverse = False
+
+    return sorted(itertools.chain(object_list1, object_list2),
+                  key=lambda x: getattr(x, field),
+                  reverse=reverse)
+
+if __name__ == "__main__":
+    import doctest
+    doctest.testmod()

Added: trunk/feeds/__init__.py
==============================================================================

Added: trunk/feeds/urls.py
==============================================================================
--- (empty file)
+++ trunk/feeds/urls.py	Wed Mar  4 15:33:15 2009
@@ -0,0 +1,12 @@
+from django.conf.urls.defaults import *
+from vertimus.feeds import LatestActionsByLanguage, LatestActionsByTeam
+
+feeds = {
+    'languages': LatestActionsByLanguage,
+    'teams': LatestActionsByTeam,
+}
+
+urlpatterns = patterns('',
+    (r'^(?P<url>.*)/$', 'django.contrib.syndication.views.feed',
+        {'feed_dict': feeds}),
+)

Added: trunk/media/img/feed-icon-10x10.png
==============================================================================
Binary file. No diff available.

Modified: trunk/settings_sample.py
==============================================================================
--- trunk/settings_sample.py	(original)
+++ trunk/settings_sample.py	Wed Mar  4 15:33:15 2009
@@ -123,7 +123,8 @@
     'people',
     'stats',
     'teams',
-    'vertimus'
+    'vertimus',
+    'feeds',
 )
 
 INTERNAL_IPS=('127.0.0.1',)

Added: trunk/templates/feeds/actions_description.html
==============================================================================
--- (empty file)
+++ trunk/templates/feeds/actions_description.html	Wed Mar  4 15:33:15 2009
@@ -0,0 +1,10 @@
+{% load i18n %}
+</p>
+{% if obj.comment %}
+{{ obj.comment }}
+{% else %}
+{% trans 'Without comment' %}
+{% endif %}
+</p>
+
+<p>{{ obj.person }}</p>

Added: trunk/templates/feeds/actions_title.html
==============================================================================
--- (empty file)
+++ trunk/templates/feeds/actions_title.html	Wed Mar  4 15:33:15 2009
@@ -0,0 +1 @@
+{{ obj.state.domain }} - {{ obj.state.branch.module.name }} ({{ obj.state.branch.name }}) - {{ obj.state }}

Modified: trunk/templates/languages/language_list.html
==============================================================================
--- trunk/templates/languages/language_list.html	(original)
+++ trunk/templates/languages/language_list.html	Wed Mar  4 15:33:15 2009
@@ -19,7 +19,12 @@
   <div class="col3_column">
     <ul class="foot">
       {% for lang in column %}
-      <li><a href="{{ lang.get_team_url }}">{{ lang.get_name }}</a></li>
+      <li>
+        <a href="{{ lang.get_team_url }}">{{ lang.get_name }}</a>
+        <a href="/rss/languages/{{ lang.locale }}">
+          <img width="10" height="10" border="0" src="{{ MEDIA_URL }}img/feed-icon-10x10.png"/> 
+        </a>
+      </li>
       {% endfor %}
     </ul>
   </div>

Modified: trunk/templates/teams/team_detail.html
==============================================================================
--- trunk/templates/teams/team_detail.html	(original)
+++ trunk/templates/teams/team_detail.html	Wed Mar  4 15:33:15 2009
@@ -1,6 +1,10 @@
 {% extends "base.html" %}
 {% load i18n %}
-
+{% block extrahead %}
+<link rel="alternate" type="application/rss+xml"
+      title="{% blocktrans with team.get_description as lang %}Last actions made by the {{ lang }} team of the GNOME translation project{% endblocktrans %}"
+      href="/rss/teams/{{ team.name }}" />
+{% endblock %}
 {% block title %}{{ team.get_description }}{% endblock %}
 
 {% block content %}

Modified: trunk/urls.py
==============================================================================
--- trunk/urls.py	(original)
+++ trunk/urls.py	Wed Mar  4 15:33:15 2009
@@ -18,6 +18,7 @@
     (r'^vertimus/', include('vertimus.urls')),
     (r'^i18n/', include('django.conf.urls.i18n')),
     (r'^admin/(.*)', admin.site.root),
+    (r'^rss/', include('feeds.urls')),
 )
 
 urlpatterns += patterns('stats.views',

Added: trunk/vertimus/feeds.py
==============================================================================
--- (empty file)
+++ trunk/vertimus/feeds.py	Wed Mar  4 15:33:15 2009
@@ -0,0 +1,114 @@
+# -*- coding: utf-8 -*-
+#
+# Copyright (c) 2009 StÃphane Raimbault <stephane raimbault gmail com>
+#
+# This file is part of Damned Lies.
+#
+# Damned Lies is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# Damned Lies is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Damned Lies; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+from django.core import urlresolvers
+from django.core.exceptions import ObjectDoesNotExist
+from django.contrib.syndication.feeds import Feed, FeedDoesNotExist
+from django.utils.translation import ugettext_lazy as _
+from django.contrib.sites.models import Site
+from languages.models import Language
+from teams.models import Team
+from vertimus.models import ActionDb, ActionDbBackup
+from common.utils import merge_sorted_by_field
+
+class LatestActionsByLanguage(Feed):
+    title_template = 'feeds/actions_title.html'
+    description_template = 'feeds/actions_description.html'
+    
+    def get_object(self, bits):
+        if len(bits) != 1:
+            raise ObjectDoesNotExist
+        return Language.objects.get(locale=bits[0])
+
+    def title(self, obj):
+        current_site = Site.objects.get_current()
+        return _("%s - Vertimus actions for the %s language") % (current_site, obj.name)
+
+    def link(self, obj):
+        if not obj:
+            raise FeedDoesNotExist
+        return obj.get_team_url()
+
+    def description(self, obj):
+        return _("Last actions of the GNOME translation project for the %s language") % obj.name
+
+    def items(self, obj):
+        # The Django ORM doesn't provide the UNION SQL feature :-(
+        # so we need to fetch twice more objects than required
+        actions_db = ActionDb.objects.filter(state_db__language=obj.id).select_related('state').order_by('-created')[:20]
+        archived_actions_db = ActionDbBackup.objects.filter(state_db__language=obj.id).select_related('state').order_by('-created')[:20]
+
+        return (action_db.get_action() for action_db in merge_sorted_by_field(actions_db, archived_actions_db, '-created')[:20])
+
+    def item_link(self, item):
+        return urlresolvers.reverse('vertimus-names-view', 
+                                    args=(item.state.branch.module.name, 
+                                          item.state.branch.name,
+                                          item.state.domain.name,
+                                          item.state.language.locale))
+
+    def item_pubdate(self, item):
+        return item.created
+
+    def item_author_name(self, item):
+        return item.person
+
+
+class LatestActionsByTeam(Feed):
+    title_template = 'feeds/actions_title.html'
+    description_template = 'feeds/actions_description.html'
+
+    def get_object(self, bits):
+        if len(bits) != 1:
+            raise ObjectDoesNotExist
+        return Team.objects.get(name=bits[0])
+
+    def title(self, obj):
+        current_site = Site.objects.get_current()
+        return _("%s - Vertimus actions of the %s team") % (current_site, obj)
+
+    def link(self, obj):
+        if not obj:
+            raise FeedDoesNotExist
+        return obj.get_absolute_url()
+
+    def description(self, obj):
+        return _("Last actions made by the %s team of the GNOME translation project") % obj
+
+    def items(self, obj):
+        # The Django ORM doesn't provide the UNION SQL feature :-(
+        # so we need to fetch twice more objects than required
+        actions_db = ActionDb.objects.filter(state_db__language__team=obj.id).select_related('state').order_by('-created')[:20]
+        archived_actions_db = ActionDbBackup.objects.filter(state_db__language__team=obj.id).select_related('state').order_by('-created')[:20]
+
+        return (action_db.get_action() for action_db in merge_sorted_by_field(actions_db, archived_actions_db, '-created')[:20])
+
+    def item_link(self, item):
+        return urlresolvers.reverse('vertimus-names-view', 
+                                    args=(item.state.branch.module.name, 
+                                          item.state.branch.name,
+                                          item.state.domain.name,
+                                          item.state.language.locale))
+
+    def item_pubdate(self, item):
+        return item.created
+
+    def item_author_name(self, item):
+        return item.person

Modified: trunk/vertimus/models.py
==============================================================================
--- trunk/vertimus/models.py	(original)
+++ trunk/vertimus/models.py	Wed Mar  4 15:33:15 2009
@@ -653,6 +653,9 @@
     class Meta:
         db_table = 'action_backup'
 
+    def __unicode__(self):
+        return "%s (%s)" % (self.name, self.id)
+
 class ActionBA(ActionAbstract):
     name = 'BA'
     description = _('Backup the actions')



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]