Login

EasyFeed class

Author:
limodou
Posted:
March 1, 2007
Language:
Python
Version:
Pre .96
Tags:
feed rss
Score:
3 (after 3 ratings)

This class simplies the Feed class of django. The differences are:

  1. Don't need define title and description template file
  2. default feed generator class is Atom1Feed
  3. According feed_url, EasyFeed can auto get the domain field, and you can also specify the domain parameter.(feed_url should be a full domain path, so you can use Get the full request path to get the full path of the feed url.)
  4. There is a helper function render_feed() to return a response value.

example

Feed class:

class BookCommentsFeed(EasyFeed):
    def __init__(self, feed_url, book_id):
        super(BookCommentsFeed, self).__init__(feed_url)
        self.book_id = book_id
        self.book = Book.objects.get(id=int(book_id))

    def link(self):
        return '/book/%s' % self.book_id

    def items(self):
        return self.book.comment_set.all().order_by('-createtime')[:15]

    def title(self):
        return 'Comments of: ' + self.book.title

    def description(self):
        return self.book.description

    def item_link(self, item):
        return '/book/%s/%s' % (self.book_id, item.chapter.num)

    def item_description(self, item):
        return item.content

    def item_title(self, item):
        return '#%d Comment for: ' % item.id + item.chapter.title

    def item_pubdate(self, item):
        return item.createtime

    def item_author_name(self, item):
        return item.username

And the view code is:

from feeds import *
from utils.easyfeed import render_feed
from utils.common import get_full_path

def bookcomments(request, book_id):
    return render_feed(BookCommentsFeed(get_full_path(request), book_id))
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
from django.utils import feedgenerator
from django.conf import settings
from django.http import HttpResponse
from django.utils.feedgenerator import Atom1Feed

def render_feed(feed):
    feedgen = feed.get_feed()
    response = HttpResponse(mimetype=feedgen.mime_type)
    feedgen.write(response, 'utf-8')
    return response

def add_domain(domain, url, prefix):
    if url.startswith('/'):
        url = url[1:]
    if not url.startswith('http://'):
        if prefix:
            url = u'%s/%s/%s' % (domain, prefix, url)
        else:
            url = u'%s/%s' % (domain, url)
    return url

class EasyFeed(object):
    item_pubdate = None
    item_enclosure_url = None
    feed_type = Atom1Feed

    def __init__(self, feed_url, domain='', prefix=''):
        self.domain = domain
        if not self.domain:
            import urlparse
            v = urlparse.urlparse(feed_url)
            self.domain = v[0] + '://' + v[1]
        if not self.domain.startswith('http://'):
            self.domain = 'http://' + self.domain
        if self.domain.endswith('/'):
            self.domain = self.domain[:-1]
        self.feed_url = feed_url
        self.prefix = prefix

    def __get_dynamic_attr(self, attname, obj=None, default=None):
        value = ''
        try:
            attr = getattr(self, attname)
        except AttributeError:
            value = default
        else:
            if callable(attr):
                # Check func_code.co_argcount rather than try/excepting the
                # function and catching the TypeError, because something inside
                # the function may raise the TypeError. This technique is more
                # accurate.
                if hasattr(attr, 'func_code'):
                    argcount = attr.func_code.co_argcount
                else:
                    argcount = attr.__call__.func_code.co_argcount
                if argcount == 2: # one argument is 'self'
                    value = attr(obj)
                else:
                    value = attr()
        if isinstance(value, str):
            value = unicode(value, settings.DEFAULT_CHARSET)

        return value
    
    def get_feed(self):
        """
        Returns a feedgenerator.DefaultFeed object, fully populated, for
        this feed. 
        """
        feed = self.feed_type(
            title = self.__get_dynamic_attr('title'),
            link = add_domain(self.domain, self.__get_dynamic_attr('link', default=''), self.prefix),
            description = self.__get_dynamic_attr('description'),
            language = settings.LANGUAGE_CODE.decode(),
            feed_url = add_domain(self.domain, self.feed_url, self.prefix),
            author_name = self.__get_dynamic_attr('author_name'),
            author_link = self.__get_dynamic_attr('author_link'),
            author_email = self.__get_dynamic_attr('author_email'),
        )

        for item in self.items():
            link = add_domain(self.domain, self.__get_dynamic_attr('item_link', item), self.prefix)
            enc = None
            enc_url = self.__get_dynamic_attr('item_enclosure_url', item)
            if enc_url:
                enc = feedgenerator.Enclosure(
                    url = enc_url.decode('utf-8'),
                    length = str(self.__get_dynamic_attr('item_enclosure_length', item)).decode('utf-8'),
                    mime_type = self.__get_dynamic_attr('item_enclosure_mime_type', item).decode('utf-8'),
                )
            author_name = self.__get_dynamic_attr('item_author_name', item)
            if author_name is not None:
                author_email = self.__get_dynamic_attr('item_author_email', item)
                author_link = self.__get_dynamic_attr('item_author_link', item)
            else:
                author_email = author_link = None
            feed.add_item(
                title = self.__get_dynamic_attr('item_title', item),
                link = link,
                description = self.__get_dynamic_attr('item_description', item),
                unique_id = link,
                enclosure = enc,
                pubdate = self.__get_dynamic_attr('item_pubdate', item),
                author_name = author_name,
                author_email = author_email,
                author_link = author_link,
            )
        return feed

    def items(self):
        raise Exception, 'Not Implemented'

More like this

  1. HTTP (basic) auth enabled (new-style) syndication framework feed class by hupf 4 years, 6 months ago
  2. Resource by zvoase 6 years, 9 months ago
  3. testdata tag for templates by showell 6 years, 1 month ago
  4. decorators for creating paramaterized decorators and easy monkeypatching by fish2000 5 years, 5 months ago
  5. Modifying the fields of a third/existing model class by marinho 4 years, 6 months ago

Comments

Please login first before commenting.