Project

General

Profile

Statistics
| Branch: | Revision:

root / env / lib / python2.7 / site-packages / django / contrib / syndication / views.py @ 1a305335

History | View | Annotate | Download (7.44 KB)

1 1a305335 officers
from django.conf import settings
2
from django.contrib.sites.models import get_current_site
3
from django.core.exceptions import ImproperlyConfigured, ObjectDoesNotExist
4
from django.http import HttpResponse, Http404
5
from django.template import loader, TemplateDoesNotExist, RequestContext
6
from django.utils import feedgenerator, tzinfo
7
from django.utils.encoding import force_unicode, iri_to_uri, smart_unicode
8
from django.utils.html import escape
9
from django.utils.timezone import is_naive
10
11
def add_domain(domain, url, secure=False):
12
    protocol = 'https' if secure else 'http'
13
    if url.startswith('//'):
14
        # Support network-path reference (see #16753) - RSS requires a protocol
15
        url = '%s:%s' % (protocol, url)
16
    elif not (url.startswith('http://')
17
            or url.startswith('https://')
18
            or url.startswith('mailto:')):
19
        # 'url' must already be ASCII and URL-quoted, so no need for encoding
20
        # conversions here.
21
        url = iri_to_uri(u'%s://%s%s' % (protocol, domain, url))
22
    return url
23
24
class FeedDoesNotExist(ObjectDoesNotExist):
25
    pass
26
27
28
class Feed(object):
29
    feed_type = feedgenerator.DefaultFeed
30
    title_template = None
31
    description_template = None
32
33
    def __call__(self, request, *args, **kwargs):
34
        try:
35
            obj = self.get_object(request, *args, **kwargs)
36
        except ObjectDoesNotExist:
37
            raise Http404('Feed object does not exist.')
38
        feedgen = self.get_feed(obj, request)
39
        response = HttpResponse(content_type=feedgen.mime_type)
40
        feedgen.write(response, 'utf-8')
41
        return response
42
43
    def item_title(self, item):
44
        # Titles should be double escaped by default (see #6533)
45
        return escape(force_unicode(item))
46
47
    def item_description(self, item):
48
        return force_unicode(item)
49
50
    def item_link(self, item):
51
        try:
52
            return item.get_absolute_url()
53
        except AttributeError:
54
            raise ImproperlyConfigured('Give your %s class a get_absolute_url() method, or define an item_link() method in your Feed class.' % item.__class__.__name__)
55
56
    def __get_dynamic_attr(self, attname, obj, default=None):
57
        try:
58
            attr = getattr(self, attname)
59
        except AttributeError:
60
            return default
61
        if callable(attr):
62
            # Check func_code.co_argcount rather than try/excepting the
63
            # function and catching the TypeError, because something inside
64
            # the function may raise the TypeError. This technique is more
65
            # accurate.
66
            if hasattr(attr, 'func_code'):
67
                argcount = attr.func_code.co_argcount
68
            else:
69
                argcount = attr.__call__.func_code.co_argcount
70
            if argcount == 2: # one argument is 'self'
71
                return attr(obj)
72
            else:
73
                return attr()
74
        return attr
75
76
    def feed_extra_kwargs(self, obj):
77
        """
78
        Returns an extra keyword arguments dictionary that is used when
79
        initializing the feed generator.
80
        """
81
        return {}
82
83
    def item_extra_kwargs(self, item):
84
        """
85
        Returns an extra keyword arguments dictionary that is used with
86
        the `add_item` call of the feed generator.
87
        """
88
        return {}
89
90
    def get_object(self, request, *args, **kwargs):
91
        return None
92
93
    def get_feed(self, obj, request):
94
        """
95
        Returns a feedgenerator.DefaultFeed object, fully populated, for
96
        this feed. Raises FeedDoesNotExist for invalid parameters.
97
        """
98
        current_site = get_current_site(request)
99
100
        link = self.__get_dynamic_attr('link', obj)
101
        link = add_domain(current_site.domain, link, request.is_secure())
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(
110
                current_site.domain,
111
                self.__get_dynamic_attr('feed_url', obj) or request.path,
112
                request.is_secure(),
113
            ),
114
            author_name = self.__get_dynamic_attr('author_name', obj),
115
            author_link = self.__get_dynamic_attr('author_link', obj),
116
            author_email = self.__get_dynamic_attr('author_email', obj),
117
            categories = self.__get_dynamic_attr('categories', obj),
118
            feed_copyright = self.__get_dynamic_attr('feed_copyright', obj),
119
            feed_guid = self.__get_dynamic_attr('feed_guid', obj),
120
            ttl = self.__get_dynamic_attr('ttl', obj),
121
            **self.feed_extra_kwargs(obj)
122
        )
123
124
        title_tmp = None
125
        if self.title_template is not None:
126
            try:
127
                title_tmp = loader.get_template(self.title_template)
128
            except TemplateDoesNotExist:
129
                pass
130
131
        description_tmp = None
132
        if self.description_template is not None:
133
            try:
134
                description_tmp = loader.get_template(self.description_template)
135
            except TemplateDoesNotExist:
136
                pass
137
138
        for item in self.__get_dynamic_attr('items', obj):
139
            if title_tmp is not None:
140
                title = title_tmp.render(RequestContext(request, {'obj': item, 'site': current_site}))
141
            else:
142
                title = self.__get_dynamic_attr('item_title', item)
143
            if description_tmp is not None:
144
                description = description_tmp.render(RequestContext(request, {'obj': item, 'site': current_site}))
145
            else:
146
                description = self.__get_dynamic_attr('item_description', item)
147
            link = add_domain(
148
                current_site.domain,
149
                self.__get_dynamic_attr('item_link', item),
150
                request.is_secure(),
151
            )
152
            enc = None
153
            enc_url = self.__get_dynamic_attr('item_enclosure_url', item)
154
            if enc_url:
155
                enc = feedgenerator.Enclosure(
156
                    url = smart_unicode(enc_url),
157
                    length = smart_unicode(self.__get_dynamic_attr('item_enclosure_length', item)),
158
                    mime_type = smart_unicode(self.__get_dynamic_attr('item_enclosure_mime_type', item))
159
                )
160
            author_name = self.__get_dynamic_attr('item_author_name', item)
161
            if author_name is not None:
162
                author_email = self.__get_dynamic_attr('item_author_email', item)
163
                author_link = self.__get_dynamic_attr('item_author_link', item)
164
            else:
165
                author_email = author_link = None
166
167
            pubdate = self.__get_dynamic_attr('item_pubdate', item)
168
            if pubdate and is_naive(pubdate):
169
                ltz = tzinfo.LocalTimezone(pubdate)
170
                pubdate = pubdate.replace(tzinfo=ltz)
171
172
            feed.add_item(
173
                title = title,
174
                link = link,
175
                description = description,
176
                unique_id = self.__get_dynamic_attr('item_guid', item, link),
177
                enclosure = enc,
178
                pubdate = pubdate,
179
                author_name = author_name,
180
                author_email = author_email,
181
                author_link = author_link,
182
                categories = self.__get_dynamic_attr('item_categories', item),
183
                item_copyright = self.__get_dynamic_attr('item_copyright', item),
184
                **self.item_extra_kwargs(item)
185
            )
186
        return feed