Ticket #329: new_rss.diff

File new_rss.diff, 8.9 KB (added by anonymous, 10 years ago)

Here is my work on the rss system

  • django/utils/feedconfigs.py

     
     1from django.utils import feedgenerator
     2from django.models.core import sites
     3from django.conf.settings import LANGUAGE_CODE, SETTINGS_MODULE
     4from django.core import template_loader
     5from django.core.template import Context
     6"""
     7This defines the parent classes for all the feed configuration objects.
     8"""
     9class RequiredFunctionError(Exception):
     10        """
     11        I saw this somewhere and liked it. This gets thrown when a required feild is not defined in a base class
     12        """
     13        def __init__(self,function):
     14                Exception.__init__(self,"Function: %s is a required method and needs to be overridden" % function.__name__)
     15
     16
     17               
     18class FeedConfiguration:
     19        """
     20        This is the base Feed Configuration class, it maps with the Syntication Feed generator
     21        """
     22        def __init__(self):
     23                pass
     24               
     25        def get_feed(self):
     26                """
     27                This return a feed generator, don't override this unless you know what your doing
     28                """
     29                pass
     30        #####
     31        ## Feed Options
     32        #####
     33        def set_param_slug(self,param_slug):
     34                raise RequiredFunctionError(self.set_param_slug)
     35
     36        def get_slug(self):
     37                raise RequiredFunctionError(self.get_slug)
     38       
     39        def _slug_getter(self):
     40                return(self.get_slug())
     41       
     42        slug = property(_slug_getter)                   
     43       
     44        def get_title(self):
     45                raise RequiredFunctionError(self.get_title)
     46       
     47        def get_description(self):
     48                return None
     49       
     50        def get_link(self):
     51                raise RequiredFunctionError(self.get_link)                     
     52
     53       
     54        def get_language(self):
     55                return None
     56
     57        def get_items(self):
     58                raise RequiredFunctionError(self.get_items)
     59               
     60        def set_current_item(self, item):
     61                raise RequiredFunctionError(self.__init__)
     62
     63        def get_item_title(self):
     64                """
     65                The default function loads the template, rss/{slug}_title.html
     66                Context:
     67                obj: The current item
     68                        site: The current site
     69                override this only if really needed.
     70                """
     71                return None
     72
     73        def get_item_description(self):
     74                """
     75                The default function loads the template, rss/{slug}_description.html
     76                Context:
     77                        obj: The current item
     78                        site: The current site
     79                override this only if really needed.
     80                """                             
     81                return None
     82
     83        def get_item_link(self):
     84                raise RequiredFunctionError(self.get_link)
     85
     86        def get_item_author_email(self):
     87                return None
     88
     89        def get_item_author_name(self):
     90                return None
     91
     92        def get_item_pub_date(self):
     93                """
     94                Returns: datetime.datetime
     95                """
     96                return None
     97
     98        def get_item_comments(self):
     99                return None
     100
     101        def get_item_unique_id(self):
     102                return None
     103
     104        def get_item_enclosure(self):
     105                """
     106                returns: dict{url,mime_type,length}
     107                """
     108                return None
     109       
     110        def get_item_categories(self):
     111                return None
     112               
     113class RssConfiguration(FeedConfiguration):
     114        def __init__(self,Generator_Class=feedgenerator.DefaultRssFeed):
     115                FeedConfiguration.__init__(self)
     116                self.generator = Generator_Class
     117               
     118        def get_feed(self, param_slug=None):
     119                """
     120                Returns a utils.feedgenerator.DefaultRssFeed object, fully populated,
     121                representing this FeedConfiguration.
     122                """
     123                current_site = sites.get_current()
     124       
     125                # Set the param slug
     126                self.set_param_slug(param_slug)
     127               
     128                # Geth the feed generator object
     129                f = self._get_feed_generator_object()
     130
     131                # Get the feed's slug
     132                slug = self.get_slug()
     133
     134
     135                # Get the feed's items
     136                for obj in self.get_items():
     137                        # Set the current item so that the object can record it
     138                        self.set_current_item(obj)
     139           
     140            # Retrieve the current item's link
     141                        link = self.get_item_link()
     142                        if not link.startswith('http://'):
     143                                link = u'http://%s%s' % (current_site.domain, link)
     144                               
     145
     146                        # Get the item's title
     147                        title = self.get_item_title()
     148            # If the title returns None (default action),
     149                        if title == None:
     150                # Generate it with the rss title template for this feed
     151                                title_template = template_loader.get_template('rss/%s_title' % slug)
     152                                title = title_template.render(Context({'obj': obj, 'site': current_site})).decode('utf-8')
     153
     154            # Get the item's description
     155                        description = self.get_item_description()
     156            # If the description is None,
     157                        if description == None:
     158                # Generate it with the rss description template for this feed
     159                                description_template = template_loader.get_template('rss/%s_description' % slug)                               
     160                                description = description_template.render(Context({'obj': obj, 'site': current_site})).decode('utf-8')
     161
     162                        #  Init the enc variable
     163                        enc = None
     164                        # Get the item's enclosure data
     165                        enc_data = self.get_item_enclosure()
     166                        # If the enclosure data is not null
     167                        if enc_data:
     168        # Create an Enclosure object with that data
     169                                enc = feedgenerator.Enclosure(enc_data['url'].decode('utf-8'),
     170                                                                                         (enc_data['length'] and str(enc_data['length']).decode('utf-8') or ''),
     171                                                                                         enc_data['mime_type'].decode('utf-8'))
     172                                             
     173            # Add the current item's data to the feed
     174                        f.add_item(
     175                                   title           = title,
     176                                   description = description,
     177                                   link         = link,
     178                                   unique_id   = link,
     179                                   enclosure   = enc,
     180                                   pubdate       = self.get_item_pub_date(),
     181                                   author_email= self.get_item_author_email(),
     182                                   author_name = self.get_item_author_name(),
     183                                   comments     = self.get_item_comments(),
     184                                   categories  = self.get_item_categories(),                                                                                                                     
     185                        )
     186                        return f
     187               
     188        def _get_feed_generator_object(self):
     189                current_site = sites.get_current()
     190                link = self.get_link().decode()
     191                if not link.startswith('http://'):
     192                        link = u'http://%s%s' % (current_site.domain, link)
     193                       
     194                return self.generator(
     195                        title = self.get_title(),
     196                        link = link,
     197                        description = self.get_description(),
     198                        language = LANGUAGE_CODE.decode(),
     199                )
     200
     201
     202def register_feed_modules(module_list):
     203        """
     204        This function takes a list of module names and registers all the FeedConfiguration objects within that module
     205        """
     206        import types
     207        from django.core import rss
     208        for module_name, attrs in module_list:
     209                        try:
     210                                # Load the module
     211                                module = __import__(module_name,'','',[''])
     212                                # loop over each item in the module,
     213                                for name,value in module.__dict__.items():
     214                                        # If the item in the module is a subclass of FeedConfiguration
     215                                        if type(value) == types.ClassType and value != FeedConfiguration and issubclass(value,FeedConfiguration):
     216                                                # if attrs is not None, init the class with the attrs
     217                                                if attrs != None:
     218                                                        feed_config = value(**attrs)
     219                                                # otherwise init it without it
     220                                                else:
     221                                                        feed_config = value()
     222
     223                                                # call the register feed function
     224                                                rss.register_feed(feed_config)
     225                        except ImportError,e:
     226                                raise e
  • tests/othertests/new_rss.py

     
     1from django.utils import feedconfigs,feedgenerator
     2"""
     3These aren't the best unittests, not all that automated but they help document how the elements work
     4"""
     5
     6import os,sys
     7# Add the current path to the template dirs so that we can get the test templates
     8
     9class FakeFeedConfig(feedconfigs.RssConfiguration):
     10
     11        # Only define the required functions so that we know that the defaults
     12        # don't kill anything
     13        def set_param_slug(self,param_slug):
     14                self.param_slug = param_slug
     15       
     16        def get_link(self):
     17                        return "/test"
     18   
     19        def get_title(self):
     20                return "title"
     21   
     22        def get_slug(self):
     23                return("test")
     24   
     25        def get_description(self):
     26                return "description"
     27   
     28        def get_items(self):
     29                items = []
     30                for i in range(0,10):
     31                        data = {
     32             'title' : 'title_%s' % i,
     33             'description' : 'title_%s' % i,
     34             'link' : 'http://example.com/%s/' % i,
     35            }
     36                        items.append(data)
     37                        return(items)
     38   
     39        def set_current_item(self,item):
     40                self.item = item
     41
     42        def get_item_link(self):
     43                return(self.item['link'])
     44   
     45        def get_item_title(self):
     46                return(self.item['title'])
     47   
     48        def get_item_description(self):
     49                return(self.item['description'])           
     50
     51if __name__ == '__main__':
     52
     53        # Lets start by testing that all the required items fail like they should
     54        fc = FakeFeedConfig()
     55        f = fc.get_feed()
     56        f.write(sys.stdout,'utf-8')
     57
     58        # Custom Generator
     59        fc = FakeFeedConfig(feedgenerator.RssUserland091Feed)
     60        f = fc.get_feed()
     61
     62        f.write(sys.stdout,'utf-8')
     63
     64        feedconfigs.register_feed_modules([
     65                        # Simple Config with no parameters
     66                                                                                                        ('new_rss',None),
     67                                                                                                        # An example of a Feed Config class with parameters, this instance is for changing the generator
     68                        ('new_rss',{'Generator_Class' : feedgenerator.RssUserland091Feed })
     69                                                                                                        ])
     70        from django.core import rss
     71       
     72        f = rss.get_registered_feed('test')
     73
     74        assert 'FakeFeedConfig' in  str(f.__class__) , "Eric, your register_feed_modules function sucks."
Back to Top