from django.conf import settings
from django.conf.urls.defaults import url, patterns, include
+from django.contrib.sites.models import Site, RequestSite
+from django.contrib.syndication.views import add_domain
from django.db import models
-from django.http import Http404
+from django.http import Http404, HttpResponse
from django.template import RequestContext, Template as DjangoTemplate
from django.utils import feedgenerator, tzinfo
from django.utils.datastructures import SortedDict
from django.utils.encoding import smart_unicode, force_unicode
from django.utils.html import escape
from datetime import date, datetime
+from philo.contrib.penfield.exceptions import HttpNotAcceptable
+from philo.contrib.penfield.middleware import http_not_acceptable
from philo.contrib.penfield.validators import validate_pagination_count
from philo.exceptions import ViewCanNotProvideSubpath
from philo.models import Tag, Titled, Entity, MultiView, Page, register_value_model, TemplateField, Template
except:
mimeparse = None
+
ATOM = feedgenerator.Atom1Feed.mime_type
RSS = feedgenerator.Rss201rev2Feed.mime_type
FEEDS = SortedDict([
feed_type = models.CharField(max_length=50, choices=FEED_CHOICES, default=ATOM)
feed_suffix = models.CharField(max_length=255, blank=False, default="feed")
feeds_enabled = models.BooleanField(default=True)
+ feed_length = models.PositiveIntegerField(blank=True, null=True, default=15, help_text="The maximum number of items to return for this feed. All items will be returned if this field is blank.")
item_title_template = models.ForeignKey(Template, blank=True, null=True, related_name="%(app_label)s_%(class)s_title_related")
item_description_template = models.ForeignKey(Template, blank=True, null=True, related_name="%(app_label)s_%(class)s_description_related")
description = ""
- def feed_patterns(self, get_items_attr, page_attr, reverse_name):
+ def feed_patterns(self, base, get_items_attr, page_attr, reverse_name):
"""
Given the name to be used to reverse this view and the names of
the attributes for the function that fetches the objects, returns
patterns suitable for inclusion in urlpatterns.
"""
- urlpatterns = patterns('',
- url(r'^$', self.page_view(get_items_attr, page_attr), name=reverse_name)
- )
+ urlpatterns = patterns('')
if self.feeds_enabled:
feed_reverse_name = "%s_feed" % reverse_name
+ feed_view = http_not_acceptable(self.feed_view(get_items_attr, feed_reverse_name))
+ feed_pattern = r'%s%s%s$' % (base, (base and base[-1] != "^") and "/" or "", self.feed_suffix)
urlpatterns += patterns('',
- url(r'^%s$' % self.feed_suffix, self.feed_view(get_items_attr, feed_reverse_name), name=feed_reverse_name),
+ url(feed_pattern, feed_view, name=feed_reverse_name),
)
+ urlpatterns += patterns('',
+ url(r"%s$" % base, self.page_view(get_items_attr, page_attr), name=reverse_name)
+ )
return urlpatterns
def get_object(self, request, **kwargs):
obj = self.get_object(request, *args, **kwargs)
feed = self.get_feed(obj, request, reverse_name)
items, xxx = get_items(request, extra_context=extra_context, *args, **kwargs)
+ self.populate_feed(feed, items, request)
response = HttpResponse(mimetype=feed.mime_type)
feed.write(response, 'utf-8')
def get_feed_type(self, request):
feed_type = self.feed_type
+ if feed_type not in FEEDS:
+ feed_type = FEEDS.keys()[0]
accept = request.META.get('HTTP_ACCEPT')
if accept and feed_type not in accept and "*/*" not in accept and "%s/*" % feed_type.split("/")[0] not in accept:
# Wups! They aren't accepting the chosen format. Is there another format we can use?
else:
feed_type = None
if not feed_type:
- # See RFC 2616
- return HttpResponse(status=406)
+ raise HttpNotAcceptable
return FEEDS[feed_type]
def get_feed(self, obj, request, reverse_name):
"""
Returns an unpopulated feedgenerator.DefaultFeed object for this object.
"""
+ try:
+ current_site = Site.objects.get_current()
+ except Site.DoesNotExist:
+ current_site = RequestSite(request)
+
feed_type = self.get_feed_type(request)
node = request.node
link = node.get_absolute_url(with_domain=True, request=request, secure=request.is_secure())
link = link,
description = self.__get_dynamic_attr('description', obj),
language = settings.LANGUAGE_CODE.decode(),
- feed_url = node.construct_url(self.reverse(reverse_name), with_domain=True, request=request, secure=request.is_secure()),
+ feed_url = add_domain(
+ current_site.domain,
+ self.__get_dynamic_attr('feed_url', obj) or node.construct_url(node.subpath, with_domain=True, request=request, secure=request.is_secure()),
+ request.is_secure()
+ ),
author_name = self.__get_dynamic_attr('author_name', obj),
author_link = self.__get_dynamic_attr('author_link', obj),
author_email = self.__get_dynamic_attr('author_email', obj),
def populate_feed(self, feed, items, request):
if self.item_title_template:
- title_template = Template(self.item_title_template.code)
+ title_template = DjangoTemplate(self.item_title_template.code)
else:
title_template = None
if self.item_description_template:
- description_template = Template(self.item_description_template.code)
+ description_template = DjangoTemplate(self.item_description_template.code)
else:
description_template = None
node = request.node
+ try:
+ current_site = Site.objects.get_current()
+ except Site.DoesNotExist:
+ current_site = RequestSite(request)
+
+ if self.feed_length is not None:
+ items = items[:self.feed_length]
for item in items:
if title_template is not None:
enc_url = self.__get_dynamic_attr('item_enclosure_url', item)
if enc_url:
enc = feedgenerator.Enclosure(
- url = smart_unicode(enc_url),
+ url = smart_unicode(add_domain(
+ current_site.domain,
+ enc_url,
+ request.is_secure()
+ )),
length = smart_unicode(self.__get_dynamic_attr('item_enclosure_length', item)),
mime_type = smart_unicode(self.__get_dynamic_attr('item_enclosure_mime_type', item))
)
index_page = models.ForeignKey(Page, related_name='blog_index_related')
entry_page = models.ForeignKey(Page, related_name='blog_entry_related')
+ # TODO: entry_archive is misleading. Rename to ymd_page or timespan_page.
entry_archive_page = models.ForeignKey(Page, related_name='blog_entry_archive_related', null=True, blank=True)
tag_page = models.ForeignKey(Page, related_name='blog_tag_related')
tag_archive_page = models.ForeignKey(Page, related_name='blog_tag_archive_related', null=True, blank=True)
if self.entry_permalink_style == 'D':
kwargs.update({'day': str(obj.date.day).zfill(2)})
return self.entry_view, [], kwargs
- elif isinstance(obj, Tag) or (isinstance(obj, models.QuerySet) and obj.model == Tag and obj):
+ elif isinstance(obj, Tag) or (isinstance(obj, models.query.QuerySet) and obj.model == Tag and obj):
if isinstance(obj, Tag):
obj = [obj]
slugs = [tag.slug for tag in obj if tag in self.get_tag_queryset()]
@property
def urlpatterns(self):
- urlpatterns = patterns('',
- url(r'^', include(self.feed_patterns('get_all_entries', 'index_page', 'index'))),
- )
- if self.feeds_enabled:
- urlpatterns += patterns('',
- url(r'^%s/(?P<tag_slugs>[-\w]+[-+/\w]*)/%s$' % (self.tag_permalink_base, self.feed_suffix), self.feed_view('get_entries_by_tag', 'entries_by_tag_feed'), name='entries_by_tag_feed'),
- )
- urlpatterns += patterns('',
- url(r'^%s/(?P<tag_slugs>[-\w]+[-+/\w]*)$' % self.tag_permalink_base, self.page_view('get_entries_by_tag', 'tag_page'), name='entries_by_tag')
- )
+ urlpatterns = self.feed_patterns(r'^', 'get_all_entries', 'index_page', 'index') +\
+ self.feed_patterns(r'^%s/(?P<tag_slugs>[-\w]+[-+/\w]*)$' % self.tag_permalink_base, 'get_entries_by_tag', 'tag_page', 'entries_by_tag')
+
if self.tag_archive_page:
urlpatterns += patterns('',
url((r'^%s$' % self.tag_permalink_base), self.tag_archive_view, name='tag_archive')
if self.entry_archive_page:
if self.entry_permalink_style in 'DMY':
- urlpatterns += patterns('',
- url(r'^(?P<year>\d{4})', include(self.feed_patterns('get_entries_by_ymd', 'entry_archive_page', 'entries_by_year')))
- )
+ urlpatterns += self.feed_patterns(r'^(?P<year>\d{4})', 'get_entries_by_ymd', 'entry_archive_page', 'entries_by_year')
if self.entry_permalink_style in 'DM':
- urlpatterns += patterns('',
- url(r'^(?P<year>\d{4})/(?P<month>\d{2})$', include(self.feed_patterns('get_entries_by_ymd', 'entry_archive_page', 'entries_by_month'))),
- )
+ urlpatterns += self.feed_patterns(r'^(?P<year>\d{4})/(?P<month>\d{2})', 'get_entries_by_ymd', 'entry_archive_page', 'entries_by_month')
if self.entry_permalink_style == 'D':
- urlpatterns += patterns('',
- url(r'^(?P<year>\d{4})/(?P<month>\d{2})/(?P<day>\d{2})$', include(self.feed_patterns('get_entries_by_ymd', 'entry_archive_page', 'entries_by_day')))
- )
+ urlpatterns += self.feed_patterns(r'^(?P<year>\d{4})/(?P<month>\d{2})/(?P<day>\d{2})', 'get_entries_by_ymd', 'entry_archive_page', 'entries_by_day')
if self.entry_permalink_style == 'D':
urlpatterns += patterns('',
obj = self.get_object(request, *args, **kwargs)
feed = self.get_feed(obj, request, reverse_name)
items, extra_context = get_items(request, extra_context=extra_context, *args, **kwargs)
+ self.populate_feed(feed, items, request)
if 'tags' in extra_context:
tags = extra_context['tags']
- feed.feed['link'] = request.node.construct_url(self.reverse(tags), with_domain=True, request=request, secure=request.is_secure())
+ feed.feed['link'] = request.node.construct_url(self.reverse(obj=tags), with_domain=True, request=request, secure=request.is_secure())
else:
tags = obj.entry_tags
item_context = {
'paginator': paginator,
'paginated_page': paginated_page,
- self.item_context_var: objects
+ self.item_context_var: items
}
else:
item_context = {
@property
def urlpatterns(self):
- urlpatterns = patterns('',
- url(r'^', include(self.feed_patterns('get_all_articles', 'index_page', 'index'))),
- url(r'^%s/(?P<numbering>.+)' % self.issue_permalink_base, include(self.feed_patterns('get_articles_by_issue', 'issue_page', 'issue')))
+ urlpatterns = self.feed_patterns(r'^', 'get_all_articles', 'index_page', 'index') + patterns('',
+ url(r'^%s/(?P<numbering>.+)$' % self.issue_permalink_base, self.page_view('get_articles_by_issue', 'issue_page'), name='issue')
)
if self.issue_archive_page:
urlpatterns += patterns('',
url(r'^%s' % self.article_permalink_base, include(self.feed_patterns('get_all_articles', 'article_archive_page', 'articles')))
)
if self.article_permalink_style in 'DMY':
- urlpatterns += patterns('',
- url(r'^%s/(?P<year>\d{4})' % self.article_permalink_base, include(self.feed_patterns('get_articles_by_ymd', 'article_archive_page', 'articles_by_year')))
- )
+ urlpatterns += self.feed_patterns(r'^%s/(?P<year>\d{4})' % self.article_permalink_base, 'get_articles_by_ymd', 'article_archive_page', 'articles_by_year')
if self.article_permalink_style in 'DM':
- urlpatterns += patterns('',
- url(r'^%s/(?P<year>\d{4})/(?P<month>\d{2})' % self.article_permalink_base, include(self.feed_patterns('get_articles_by_ymd', 'article_archive_page', 'articles_by_month')))
- )
+ urlpatterns += self.feed_patterns(r'^%s/(?P<year>\d{4})/(?P<month>\d{2})' % self.article_permalink_base, 'get_articles_by_ymd', 'article_archive_page', 'articles_by_month')
if self.article_permalink_style == 'D':
- urlpatterns += patterns('',
- url(r'^%s/(?P<year>\d{4})/(?P<month>\d{2})/(?P<day>\d{2})' % self.article_permalink_base, include(self.feed_patterns('get_articles_by_ymd', 'article_archive_page', 'articles_by_day')))
- )
+ urlpatterns += self.feed_patterns(r'^%s/(?P<year>\d{4})/(?P<month>\d{2})/(?P<day>\d{2})' % self.article_permalink_base, 'get_articles_by_ymd', 'article_archive_page', 'articles_by_day')
if self.article_permalink_style == 'Y':
urlpatterns += patterns('',