Josh VanderLinden avatar Josh VanderLinden committed 9082830

Fixing some problems with the Tag feeds; making it easier to apply a tag to multiple articles at once in the admin

Comments (0)

Files changed (2)


+import logging
 from django.contrib import admin
 from django.contrib.auth.models import User
 from django.utils.translation import ugettext_lazy as _
 from forms import ArticleAdminForm
 from models import Tag, Article, ArticleStatus, Attachment
+log = logging.getLogger('articles.admin')
 class TagAdmin(admin.ModelAdmin):
     list_display = ('name', 'article_count')
     max_num = 15
 class ArticleAdmin(admin.ModelAdmin):
-    list_display = ('title', 'status', 'author', 'publish_date', 'expiration_date', 'is_active')
-    list_filter = ('author', 'status', 'is_active', 'publish_date', 'expiration_date', 'sites')
+    list_display = ('title', 'tag_count', 'status', 'author', 'publish_date',
+                    'expiration_date', 'is_active')
+    list_filter = ('author', 'status', 'is_active', 'publish_date',
+                   'expiration_date', 'sites')
     list_per_page = 25
     search_fields = ('title', 'keywords', 'description', 'content')
     date_hierarchy = 'publish_date'
     filter_horizontal = ('tags', 'followup_for', 'related_articles')
     prepopulated_fields = {'slug': ('title',)}
+    def tag_count(self, obj):
+        return str(obj.tags.count())
+    tag_count.short_description = _('Tags')
     def mark_active(self, request, queryset):
     mark_active.short_description = _('Mark select articles as active')
     def get_actions(self, request):
         actions = super(ArticleAdmin, self).get_actions(request)
-        def dynamic(name, status):
+        def dynamic_status(name, status):
             def status_func(self, request, queryset):
         for status in ArticleStatus.objects.all():
             name = 'mark_status_%i' %
-            actions[name] = (dynamic(name, status), name, _('Set status of selected to "%s"' % status))
+            actions[name] = (dynamic_status(name, status), name, _('Set status of selected to "%s"' % status))
+        def dynamic_tag(name, tag):
+            def status_func(self, request, queryset):
+                for article in queryset.iterator():
+                    log.debug('Dynamic tagging: applying Tag "%s" to Article "%s"' % (tag, article))
+                    article.tags.add(tag)
+            status_func.__name__ = name
+            status_func.short_description = _('Apply tag "%s" to selected articles' % tag)
+            return status_func
+        for tag in Tag.objects.all():
+            name = 'apply_tag_%s' %
+            actions[name] = (dynamic_tag(name, tag), name, _('Apply Tag: %s' % (tag.slug,)))
         return actions


 class TagFeed(Feed, SiteMixin):
-    def get_object(self, bits):
-        if len(bits) != 1:
+    def get_object(self, request, slug):
+        try:
+            return Tag.objects.get(slug__iexact=slug)
+        except Tag.DoesNotExist:
             raise FeedDoesNotExist
-        return Tag.objects.get(name__iexact=bits[0])
     def title(self, obj):
         return "%s: Newest Articles Tagged '%s'" % (,
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.