neue Verzeichnissstruktur
This commit is contained in:
1
aggregator/__init__.py
Normal file
1
aggregator/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
|
||||
17
aggregator/admin.py
Normal file
17
aggregator/admin.py
Normal file
@@ -0,0 +1,17 @@
|
||||
from django.contrib import admin
|
||||
from models import Feed, FeedItem
|
||||
|
||||
admin.site.register(Feed,
|
||||
list_display=["title", "public_url", "last_update", 'is_functional'],
|
||||
list_filter=["is_functional"],
|
||||
ordering=["title"],
|
||||
search_fields=["title", "public_url"],
|
||||
list_per_page=500,
|
||||
)
|
||||
|
||||
admin.site.register(FeedItem,
|
||||
list_display=['title', 'feed', 'date_modified'],
|
||||
list_filter=['feed'],
|
||||
search_fields=['feed__title', 'feed__public_url', 'title'],
|
||||
date_heirarchy=['date_modified'],
|
||||
)
|
||||
23
aggregator/feeds.py
Normal file
23
aggregator/feeds.py
Normal file
@@ -0,0 +1,23 @@
|
||||
import django.contrib.syndication.views
|
||||
from .models import FeedItem
|
||||
|
||||
|
||||
class LatestFeedItems(django.contrib.syndication.views.Feed):
|
||||
link = "http://aol.animanga.at/"
|
||||
description = "Aktuelle Nachrichten aus der Austrian Otaku League"
|
||||
title = "AOL - Newsfeed"
|
||||
|
||||
def items(self, obj):
|
||||
return FeedItem.objects.get_recent_items()
|
||||
|
||||
def item_title(self, item):
|
||||
return "%s: %s" % (item.feed.title, item.title)
|
||||
|
||||
def item_description(self, item):
|
||||
return item.summary
|
||||
|
||||
def item_author_name(self, item):
|
||||
return item.feed.title
|
||||
|
||||
def item_pubdate(self, item):
|
||||
return item.date_modified
|
||||
1
aggregator/management/__init__.py
Normal file
1
aggregator/management/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
# -
|
||||
1
aggregator/management/commands/__init__.py
Normal file
1
aggregator/management/commands/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
#
|
||||
59
aggregator/management/commands/update-feeds.py
Normal file
59
aggregator/management/commands/update-feeds.py
Normal file
@@ -0,0 +1,59 @@
|
||||
"""
|
||||
Update feeds for Django community page. Requires Mark Pilgrim's excellent
|
||||
Universal Feed Parser (http://feedparser.org)
|
||||
"""
|
||||
|
||||
from aggregator.models import Feed
|
||||
from django.core.management.base import BaseCommand
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = "Updates all RSS Feeds"
|
||||
|
||||
def parse_feed(self, feed, verbose=True):
|
||||
parsed_feed = feedparser.parse(feed.feed_url)
|
||||
html_parser = HTMLParser.HTMLParser()
|
||||
for entry in parsed_feed:
|
||||
title = entry.title.encode(parsed_feed.encoding, "xmlcharrefreplace")
|
||||
guid = entry.get("id", entry.link).encode(parsed_feed.encoding, "xmlcharrefreplace")
|
||||
link = entry.link.encode(parsed_feed.encoding, "xmlcharrefreplace")
|
||||
if verbose:
|
||||
print '>' , title
|
||||
|
||||
if not guid:
|
||||
guid = link
|
||||
|
||||
if hasattr(entry, "summary"):
|
||||
content = entry.summary
|
||||
elif hasattr(entry, "content"):
|
||||
content = entry.content[0].value
|
||||
elif hasattr(entry, "description"):
|
||||
content = entry.description
|
||||
else:
|
||||
content = u""
|
||||
content = content.encode(parsed_feed.encoding, "xmlcharrefreplace")
|
||||
|
||||
try:
|
||||
if entry.has_key('modified_parsed'):
|
||||
date_modified = datetime.fromtimestamp(time.mktime(entry.modified_parsed))
|
||||
elif parsed_feed.feed.has_key('modified_parsed'):
|
||||
date_modified = datetime.fromtimestamp(time.mktime(parsed_feed.feed.modified_parsed))
|
||||
elif parsed_feed.has_key('modified'):
|
||||
date_modified = datetime.fromtimestamp(time.mktime(parsed_feed.modified))
|
||||
else:
|
||||
date_modified = datetime.now()
|
||||
except TypeError:
|
||||
date_modified = datetime.now()
|
||||
|
||||
try:
|
||||
feed.feeditem_set.get(guid=guid)
|
||||
except FeedItem.DoesNotExist:
|
||||
feed.feeditem_set.create(title=title, link=link, summary=content, guid=guid, date_modified=date_modified)
|
||||
|
||||
def handle(self, *args, **options):
|
||||
verbose = int(options['verbosity']) > 0
|
||||
for feed in Feed.objects.filter(is_functional=True):
|
||||
if (verbose):
|
||||
print
|
||||
print "%s - URL: %s" % (feed.title, feed.feed_url)
|
||||
print '=' * 80
|
||||
feed.parse()
|
||||
101
aggregator/models.py
Normal file
101
aggregator/models.py
Normal file
@@ -0,0 +1,101 @@
|
||||
'''
|
||||
Created on 05.02.2011
|
||||
|
||||
@author: christian
|
||||
'''
|
||||
|
||||
from datetime import datetime, timedelta
|
||||
from django.conf import settings
|
||||
from django.contrib.sites.models import Site
|
||||
from django.utils import timezone
|
||||
from utils.html5 import models
|
||||
import HTMLParser
|
||||
import django.db.models
|
||||
import feedparser
|
||||
import urllib2
|
||||
|
||||
class FeedManager(django.db.models.Manager):
|
||||
|
||||
def active(self):
|
||||
site = settings.SITE_ID
|
||||
feeds = self.filter(is_functional=True, site=site)
|
||||
for feed in feeds:
|
||||
if feed.last_update:
|
||||
feed_age = timezone.now() - feed.last_update
|
||||
if feed_age > timedelta(hours=12):
|
||||
feed.parse()
|
||||
else:
|
||||
feed.parse()
|
||||
return feeds
|
||||
|
||||
class FeedItemManager(django.db.models.Manager):
|
||||
|
||||
def recent_items(self, max_items=10, site=None):
|
||||
site = site or settings.SITE_ID
|
||||
return self.select_related().filter(feed__site=site)[:max_items]
|
||||
|
||||
class Feed(models.Model):
|
||||
title = models.CharField(max_length=500)
|
||||
site = models.ForeignKey(Site)
|
||||
feed_url = models.URLField(unique=True, max_length=255)
|
||||
public_url = models.URLField(max_length=255)
|
||||
last_update = models.DateTimeField(blank=True, null=True)
|
||||
is_functional = models.BooleanField(default=True)
|
||||
objects = FeedManager()
|
||||
|
||||
def __unicode__(self):
|
||||
return self.title
|
||||
|
||||
def parse(self):
|
||||
parsed_feed = feedparser.parse(self.feed_url)
|
||||
html_parser = HTMLParser.HTMLParser()
|
||||
|
||||
if parsed_feed.bozo and type(parsed_feed.bozo_exception) == urllib2.URLError:
|
||||
self.is_functional = False
|
||||
return self.save()
|
||||
|
||||
for feed_entry in parsed_feed.entries:
|
||||
title = html_parser.unescape(feed_entry.title)
|
||||
if not title:
|
||||
continue
|
||||
|
||||
link = feed_entry.link
|
||||
guid = feed_entry.get("id", link)
|
||||
summary = html_parser.unescape(feed_entry.get("summary",
|
||||
feed_entry.get("description", feed_entry.get("content", u""))
|
||||
))
|
||||
date_modified = feed_entry.get("published_parsed", parsed_feed.get("published_parsed", timezone.now))
|
||||
date_modified = timezone.make_aware(datetime(*date_modified[:6]), timezone.get_current_timezone())
|
||||
|
||||
feed_item, updated = self.feed_items.get_or_create(guid=guid,
|
||||
defaults={
|
||||
'title': title,
|
||||
'link': link,
|
||||
'summary': summary,
|
||||
'date_modified': date_modified
|
||||
})
|
||||
feed_item.save()
|
||||
self.last_update = timezone.now()
|
||||
return self.save()
|
||||
|
||||
class Meta:
|
||||
ordering = ("title",)
|
||||
|
||||
|
||||
class FeedItem(models.Model):
|
||||
feed = models.ForeignKey(Feed, related_name='feed_items')
|
||||
title = models.CharField(max_length=500)
|
||||
link = models.URLField(max_length=500)
|
||||
guid = models.CharField(max_length=255, unique=True, db_index=True)
|
||||
summary = models.TextField(blank=True)
|
||||
date_modified = models.DateTimeField()
|
||||
objects = FeedItemManager()
|
||||
|
||||
class Meta:
|
||||
ordering = ("-date_modified",)
|
||||
|
||||
def __unicode__(self):
|
||||
return self.title
|
||||
|
||||
def get_absolute_url(self):
|
||||
return self.link
|
||||
12
aggregator/sitemaps.py
Normal file
12
aggregator/sitemaps.py
Normal file
@@ -0,0 +1,12 @@
|
||||
from django.contrib.sitemaps import Sitemap
|
||||
from models import FeedItem
|
||||
|
||||
class FeedItemSitemap(Sitemap):
|
||||
changefreq = "never"
|
||||
priority = 0.5
|
||||
|
||||
def items(self):
|
||||
return FeedItem.objects.get_recent_items()
|
||||
|
||||
def lastmod(self, obj):
|
||||
return obj.date_modified
|
||||
29
aggregator/templatetags/aggregator.py
Normal file
29
aggregator/templatetags/aggregator.py
Normal file
@@ -0,0 +1,29 @@
|
||||
from django import template
|
||||
from aggregator.models import Feed
|
||||
|
||||
|
||||
class FeedListNode(template.Node):
|
||||
|
||||
def __init__(self, varname):
|
||||
self.varname = varname
|
||||
|
||||
def render(self, context):
|
||||
context[self.varname] = Feed.objects.filter(is_defunct=False)
|
||||
return ''
|
||||
|
||||
|
||||
def do_get_feed_list(parser, token):
|
||||
"""
|
||||
{% get_feed_list as feed_list %}
|
||||
"""
|
||||
bits = token.contents.split()
|
||||
if len(bits) != 3:
|
||||
raise template.TemplateSyntaxError, \
|
||||
"'%s' tag takes two arguments" % bits[0]
|
||||
if bits[1] != "as":
|
||||
raise template.TemplateSyntaxError, \
|
||||
"First argument to '%s' tag must be 'as'" % bits[0]
|
||||
return FeedListNode(bits[2])
|
||||
|
||||
register = template.Library()
|
||||
register.tag('get_feed_list', do_get_feed_list)
|
||||
Reference in New Issue
Block a user