2005-11-12 11:44:53 +08:00
from django . core . exceptions import ImproperlyConfigured , ObjectDoesNotExist
2006-05-02 09:31:56 +08:00
from django . template import Context , loader , Template , TemplateDoesNotExist
from django . contrib . sites . models import Site
2005-11-12 11:44:53 +08:00
from django . utils import feedgenerator
2006-05-02 09:31:56 +08:00
from django . conf import settings
2005-11-12 11:44:53 +08:00
def add_domain ( domain , url ) :
if not url . startswith ( ' http:// ' ) :
url = u ' http:// %s %s ' % ( domain , url )
return url
class FeedDoesNotExist ( ObjectDoesNotExist ) :
pass
2006-06-08 13:00:13 +08:00
class Feed ( object ) :
2005-11-12 11:44:53 +08:00
item_pubdate = None
item_enclosure_url = None
feed_type = feedgenerator . DefaultFeed
2006-06-27 07:19:03 +08:00
title_template = None
description_template = None
2005-11-12 11:44:53 +08:00
2005-11-14 12:59:20 +08:00
def __init__ ( self , slug , feed_url ) :
2005-11-12 11:44:53 +08:00
self . slug = slug
2005-11-14 12:59:20 +08:00
self . feed_url = feed_url
2006-06-27 07:19:03 +08:00
self . title_template_name = self . title_template or ( ' feeds/ %s _title.html ' % slug )
self . description_template_name = self . description_template or ( ' feeds/ %s _description.html ' % slug )
2005-11-12 11:44:53 +08:00
def item_link ( self , item ) :
try :
return item . get_absolute_url ( )
except AttributeError :
raise ImproperlyConfigured , " Give your %s class a get_absolute_url() method, or define an item_link() method in your Feed class. " % item . __class__ . __name__
2005-11-14 13:15:40 +08:00
def __get_dynamic_attr ( self , attname , obj , default = None ) :
try :
attr = getattr ( self , attname )
except AttributeError :
return default
2005-11-12 11:44:53 +08:00
if callable ( attr ) :
2006-02-19 04:34:14 +08:00
# 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'
2005-11-12 11:44:53 +08:00
return attr ( obj )
2006-02-19 04:34:14 +08:00
else :
2005-11-12 11:44:53 +08:00
return attr ( )
return attr
def get_feed ( self , url = None ) :
"""
Returns a feedgenerator . DefaultFeed object , fully populated , for
this feed . Raises FeedDoesNotExist for invalid parameters .
"""
if url :
try :
obj = self . get_object ( url . split ( ' / ' ) )
except ( AttributeError , ObjectDoesNotExist ) :
raise FeedDoesNotExist
else :
obj = None
2006-05-02 09:31:56 +08:00
current_site = Site . objects . get_current ( )
2005-11-12 11:44:53 +08:00
link = self . __get_dynamic_attr ( ' link ' , obj )
link = add_domain ( current_site . domain , link )
feed = self . feed_type (
title = self . __get_dynamic_attr ( ' title ' , obj ) ,
link = link ,
description = self . __get_dynamic_attr ( ' description ' , obj ) ,
2006-05-02 09:31:56 +08:00
language = settings . LANGUAGE_CODE . decode ( ) ,
2006-07-21 23:57:50 +08:00
feed_url = add_domain ( current_site , self . __get_dynamic_attr ( ' feed_url ' , obj ) ) ,
2005-11-14 13:15:40 +08:00
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 ) ,
2006-06-19 09:38:06 +08:00
categories = self . __get_dynamic_attr ( ' categories ' , obj ) ,
2007-02-10 16:36:39 +08:00
feed_copyright = self . __get_dynamic_attr ( ' feed_copyright ' , obj ) ,
2005-11-12 11:44:53 +08:00
)
try :
2006-06-27 07:19:03 +08:00
title_tmp = loader . get_template ( self . title_template_name )
2005-11-12 11:44:53 +08:00
except TemplateDoesNotExist :
2006-06-27 07:19:03 +08:00
title_tmp = Template ( ' {{ obj }} ' )
2005-11-12 11:44:53 +08:00
try :
2006-06-27 07:19:03 +08:00
description_tmp = loader . get_template ( self . description_template_name )
2005-11-12 11:44:53 +08:00
except TemplateDoesNotExist :
2006-06-27 07:19:03 +08:00
description_tmp = Template ( ' {{ obj }} ' )
2005-11-12 11:44:53 +08:00
for item in self . __get_dynamic_attr ( ' items ' , obj ) :
link = add_domain ( current_site . domain , self . __get_dynamic_attr ( ' item_link ' , item ) )
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 ' ) ,
)
2005-11-14 13:15:40 +08:00
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
2005-11-12 11:44:53 +08:00
feed . add_item (
2006-06-27 07:19:03 +08:00
title = title_tmp . render ( Context ( { ' obj ' : item , ' site ' : current_site } ) ) . decode ( ' utf-8 ' ) ,
2005-11-12 11:44:53 +08:00
link = link ,
2006-06-27 07:19:03 +08:00
description = description_tmp . render ( Context ( { ' obj ' : item , ' site ' : current_site } ) ) . decode ( ' utf-8 ' ) ,
2005-11-12 11:44:53 +08:00
unique_id = link ,
enclosure = enc ,
pubdate = self . __get_dynamic_attr ( ' item_pubdate ' , item ) ,
2005-11-14 13:15:40 +08:00
author_name = author_name ,
author_email = author_email ,
author_link = author_link ,
2006-06-19 09:38:06 +08:00
categories = self . __get_dynamic_attr ( ' item_categories ' , item ) ,
2007-02-10 16:36:39 +08:00
item_copyright = self . __get_dynamic_attr ( ' item_copyright ' , item ) ,
2005-11-12 11:44:53 +08:00
)
return feed