~ubuntu-branches/ubuntu/quantal/python-django/quantal-security

« back to all changes in this revision

Viewing changes to django/contrib/syndication/feeds.py

  • Committer: Bazaar Package Importer
  • Author(s): Chris Lamb
  • Date: 2010-05-21 07:52:55 UTC
  • mfrom: (1.3.6 upstream)
  • mto: This revision was merged to the branch mainline in revision 28.
  • Revision ID: james.westby@ubuntu.com-20100521075255-ii78v1dyfmyu3uzx
Tags: upstream-1.2
ImportĀ upstreamĀ versionĀ 1.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
from datetime import datetime, timedelta
2
 
 
3
 
from django.core.exceptions import ImproperlyConfigured, ObjectDoesNotExist
4
 
from django.template import loader, Template, TemplateDoesNotExist
5
 
from django.contrib.sites.models import Site, RequestSite
6
 
from django.utils import feedgenerator
7
 
from django.utils.tzinfo import FixedOffset
8
 
from django.utils.encoding import smart_unicode, iri_to_uri
9
 
from django.conf import settings         
10
 
from django.template import RequestContext
11
 
 
12
 
def add_domain(domain, url):
13
 
    if not (url.startswith('http://') or url.startswith('https://')):
14
 
        # 'url' must already be ASCII and URL-quoted, so no need for encoding
15
 
        # conversions here.
16
 
        url = iri_to_uri(u'http://%s%s' % (domain, url))
17
 
    return url
18
 
 
19
 
class FeedDoesNotExist(ObjectDoesNotExist):
20
 
    pass
21
 
 
22
 
class Feed(object):
23
 
    item_pubdate = None
24
 
    item_enclosure_url = None
25
 
    feed_type = feedgenerator.DefaultFeed
26
 
    feed_url = None
27
 
    title_template = None
28
 
    description_template = None
29
 
 
 
1
from django.contrib.syndication import views
 
2
from django.core.exceptions import ObjectDoesNotExist
 
3
import warnings
 
4
 
 
5
# This is part of the deprecated API
 
6
from django.contrib.syndication.views import FeedDoesNotExist, add_domain
 
7
 
 
8
class Feed(views.Feed):
 
9
    """Provided for backwards compatibility."""
30
10
    def __init__(self, slug, request):
 
11
        warnings.warn('The syndication feeds.Feed class is deprecated. Please '
 
12
                      'use the new class based view API.',
 
13
                      category=PendingDeprecationWarning)
 
14
 
31
15
        self.slug = slug
32
16
        self.request = request
33
 
        self.feed_url = self.feed_url or request.path
34
 
        self.title_template_name = self.title_template or ('feeds/%s_title.html' % slug)
35
 
        self.description_template_name = self.description_template or ('feeds/%s_description.html' % slug)
36
 
 
37
 
    def item_link(self, item):
38
 
        try:
39
 
            return item.get_absolute_url()
40
 
        except AttributeError:
41
 
            raise ImproperlyConfigured, "Give your %s class a get_absolute_url() method, or define an item_link() method in your Feed class." % item.__class__.__name__
42
 
 
43
 
    def __get_dynamic_attr(self, attname, obj, default=None):
44
 
        try:
45
 
            attr = getattr(self, attname)
46
 
        except AttributeError:
47
 
            return default
48
 
        if callable(attr):
49
 
            # Check func_code.co_argcount rather than try/excepting the
50
 
            # function and catching the TypeError, because something inside
51
 
            # the function may raise the TypeError. This technique is more
52
 
            # accurate.
53
 
            if hasattr(attr, 'func_code'):
54
 
                argcount = attr.func_code.co_argcount
55
 
            else:
56
 
                argcount = attr.__call__.func_code.co_argcount
57
 
            if argcount == 2: # one argument is 'self'
58
 
                return attr(obj)
59
 
            else:
60
 
                return attr()
61
 
        return attr
62
 
 
63
 
    def feed_extra_kwargs(self, obj):
64
 
        """
65
 
        Returns an extra keyword arguments dictionary that is used when
66
 
        initializing the feed generator.
67
 
        """
68
 
        return {}
69
 
 
70
 
    def item_extra_kwargs(self, item):
71
 
        """
72
 
        Returns an extra keyword arguments dictionary that is used with
73
 
        the `add_item` call of the feed generator.
74
 
        """
75
 
        return {}
 
17
        self.feed_url = getattr(self, 'feed_url', None) or request.path
 
18
        self.title_template = self.title_template or ('feeds/%s_title.html' % slug)
 
19
        self.description_template = self.description_template or ('feeds/%s_description.html' % slug)
76
20
 
77
21
    def get_object(self, bits):
78
22
        return None
86
30
            bits = url.split('/')
87
31
        else:
88
32
            bits = []
89
 
 
90
33
        try:
91
34
            obj = self.get_object(bits)
92
35
        except ObjectDoesNotExist:
93
36
            raise FeedDoesNotExist
94
 
 
95
 
        if Site._meta.installed:
96
 
            current_site = Site.objects.get_current()
97
 
        else:
98
 
            current_site = RequestSite(self.request)
99
 
        
100
 
        link = self.__get_dynamic_attr('link', obj)
101
 
        link = add_domain(current_site.domain, link)
102
 
 
103
 
        feed = self.feed_type(
104
 
            title = self.__get_dynamic_attr('title', obj),
105
 
            subtitle = self.__get_dynamic_attr('subtitle', obj),
106
 
            link = link,
107
 
            description = self.__get_dynamic_attr('description', obj),
108
 
            language = settings.LANGUAGE_CODE.decode(),
109
 
            feed_url = add_domain(current_site.domain,
110
 
                                  self.__get_dynamic_attr('feed_url', obj)),
111
 
            author_name = self.__get_dynamic_attr('author_name', obj),
112
 
            author_link = self.__get_dynamic_attr('author_link', obj),
113
 
            author_email = self.__get_dynamic_attr('author_email', obj),
114
 
            categories = self.__get_dynamic_attr('categories', obj),
115
 
            feed_copyright = self.__get_dynamic_attr('feed_copyright', obj),
116
 
            feed_guid = self.__get_dynamic_attr('feed_guid', obj),
117
 
            ttl = self.__get_dynamic_attr('ttl', obj),
118
 
            **self.feed_extra_kwargs(obj)
119
 
        )
120
 
 
121
 
        try:
122
 
            title_tmp = loader.get_template(self.title_template_name)
123
 
        except TemplateDoesNotExist:
124
 
            title_tmp = Template('{{ obj }}')
125
 
        try:
126
 
            description_tmp = loader.get_template(self.description_template_name)
127
 
        except TemplateDoesNotExist:
128
 
            description_tmp = Template('{{ obj }}')
129
 
 
130
 
        for item in self.__get_dynamic_attr('items', obj):
131
 
            link = add_domain(current_site.domain, self.__get_dynamic_attr('item_link', item))
132
 
            enc = None
133
 
            enc_url = self.__get_dynamic_attr('item_enclosure_url', item)
134
 
            if enc_url:
135
 
                enc = feedgenerator.Enclosure(
136
 
                    url = smart_unicode(enc_url),
137
 
                    length = smart_unicode(self.__get_dynamic_attr('item_enclosure_length', item)),
138
 
                    mime_type = smart_unicode(self.__get_dynamic_attr('item_enclosure_mime_type', item))
139
 
                )
140
 
            author_name = self.__get_dynamic_attr('item_author_name', item)
141
 
            if author_name is not None:
142
 
                author_email = self.__get_dynamic_attr('item_author_email', item)
143
 
                author_link = self.__get_dynamic_attr('item_author_link', item)
144
 
            else:
145
 
                author_email = author_link = None
146
 
 
147
 
            pubdate = self.__get_dynamic_attr('item_pubdate', item)
148
 
            if pubdate and not pubdate.tzinfo:
149
 
                now = datetime.now()
150
 
                utcnow = datetime.utcnow()
151
 
 
152
 
                # Must always subtract smaller time from larger time here.
153
 
                if utcnow > now:
154
 
                    sign = -1
155
 
                    tzDifference = (utcnow - now)
156
 
                else:
157
 
                    sign = 1
158
 
                    tzDifference = (now - utcnow)
159
 
 
160
 
                # Round the timezone offset to the nearest half hour.
161
 
                tzOffsetMinutes = sign * ((tzDifference.seconds / 60 + 15) / 30) * 30
162
 
                tzOffset = timedelta(minutes=tzOffsetMinutes)
163
 
                pubdate = pubdate.replace(tzinfo=FixedOffset(tzOffset))
164
 
 
165
 
            feed.add_item(
166
 
                title = title_tmp.render(RequestContext(self.request, {'obj': item, 'site': current_site})),
167
 
                link = link,
168
 
                description = description_tmp.render(RequestContext(self.request, {'obj': item, 'site': current_site})),
169
 
                unique_id = self.__get_dynamic_attr('item_guid', item, link),
170
 
                enclosure = enc,
171
 
                pubdate = pubdate,
172
 
                author_name = author_name,
173
 
                author_email = author_email,
174
 
                author_link = author_link,
175
 
                categories = self.__get_dynamic_attr('item_categories', item),
176
 
                item_copyright = self.__get_dynamic_attr('item_copyright', item),
177
 
                **self.item_extra_kwargs(item)
178
 
            )
179
 
        return feed
 
37
        return super(Feed, self).get_feed(obj, self.request)
 
38