Django

Code

Ticket #6547: georss_syndication_patch.diff

File georss_syndication_patch.diff, 12.4 kB (added by jbronn, 5 months ago)

Patch for GeoRSS; also includes some internal changes to Feed

  • django/contrib/gis/feeds.py

    old new  
     1from django.contrib.syndication.feeds import Feed as BaseFeed, FeedDoesNotExist 
     2from django.utils.feedgenerator import Atom1Feed, Rss201rev2Feed 
     3 
     4def georss_coords(coords): 
     5    """ 
     6    In GeoRSS coordinate pairs are ordered by lat/lon and separated by 
     7    a single white space.  Given a tuple of coordinates, this will return 
     8    a unicode GeoRSS representation. 
     9    """ 
     10    return u' '.join([u'%f %f' % (coord[1], coord[0]) for coord in coords]) 
     11 
     12def add_georss_element(handler, item): 
     13    """ 
     14    This routine adds a GeoRSS XML element for the given item.  
     15    """ 
     16    # Getting the Geometry object. 
     17    geom = item.get('geometry', None) 
     18    if not geom is None: 
     19        if isinstance(geom, (list, tuple)): 
     20            # Special case if a bounding box/extent was bassed in as a 2-tuple 
     21            # ( (X0, Y0), (X1, Y1) ) or a 4-tuple (X0, Y0, X1, Y1). 
     22            if len(geom) == 2: 
     23                handler.addQuickElement(u'georss:box', georss_coords(geom)) 
     24            elif len(geom) == 4: 
     25                handler.addQuickElement(u'georss:box', georss_coords((geom[:2], geom[2:]))) 
     26            else: 
     27                raise ValueError 
     28        else: 
     29            gtype = str(geom.geom_type).lower() 
     30            if gtype == 'point': 
     31                handler.addQuickElement(u'georss:point', georss_coords((geom.coords,))) 
     32            elif gtype in ('linestring', 'linearring'): 
     33                handler.addQuickElement(u'georss:line', georss_coords(geom.coords)) 
     34            elif gtype in ('polygon'): 
     35                # Only support the exterior ring. 
     36                handler.addQuickElement(u'georss:polygon', georss_coords(geom[0].coords)) 
     37            else: 
     38                raise TypeError('Geometry type "%s" not supported.' % geom.geom_type) 
     39 
     40class GeoRSSFeed(Rss201rev2Feed): 
     41    def rss_attributes(self): 
     42        attrs = super(GeoRSSFeed, self).rss_attributes() 
     43        attrs[u'xmlns:georss'] = u'http://www.georss.org/georss' 
     44        return attrs 
     45 
     46    def add_item_elements(self, handler, item): 
     47        super(GeoRSSFeed, self).add_item_elements(handler, item) 
     48        add_georss_element(handler, item) 
     49 
     50    def add_root_elements(self, handler): 
     51        super(GeoRSSFeed, self).add_root_elements(handler) 
     52        add_georss_element(handler, self.feed) 
     53 
     54class GeoAtom1Feed(Atom1Feed): 
     55    def root_attributes(self): 
     56        attrs = super(GeoAtom1Feed, self).root_attributes() 
     57        attrs[u'xmlns:georss'] = u'http://www.georss.org/georss' 
     58        return attrs 
     59 
     60    def add_item_elements(self, handler, item): 
     61        super(GeoAtom1Feed, self).add_item_elements(handler, item) 
     62        add_georss_element(handler, item) 
     63 
     64    def add_root_elements(self, handler): 
     65        super(GeoAtom1Feed, self).add_root_elements(handler) 
     66        add_georss_element(handler, self.feed) 
     67         
     68class Feed(BaseFeed): 
     69    feed_type = GeoRSSFeed 
     70    #feed_type = GeoAtom1Feed 
     71 
     72    def get_feed_kwargs(self, obj): 
     73        kwargs = super(Feed, self).get_feed_kwargs(obj) 
     74        kwargs['geometry'] = self.__get_dynamic_attr('geometry', obj) 
     75        return kwargs 
     76 
     77    def get_item_kwargs(self, item): 
     78        kwargs = super(Feed, self).get_item_kwargs(item) 
     79        kwargs['geometry'] = self.__get_dynamic_attr('item_geometry', item) 
     80        return kwargs 
  • django/contrib/syndication/feeds.py

    old new  
    6262    def get_object(self, bits): 
    6363        return None 
    6464 
     65    def get_feed_kwargs(self, obj): 
     66        """ 
     67        Returns the keyword arguments to instatiate the `SyndicationFeed` 
     68        class specified by the `feed_type` attribute. 
     69        """ 
     70        return { 
     71            'title' : self.__get_dynamic_attr('title', obj), 
     72            'subtitle' : self.__get_dynamic_attr('subtitle', obj), 
     73            'link' : add_domain(self.current_site.domain, 
     74                                self.__get_dynamic_attr('link', obj)), 
     75            'description' : self.__get_dynamic_attr('description', obj), 
     76            'language' : settings.LANGUAGE_CODE.decode(), 
     77            'feed_url' : add_domain(self.current_site.domain, 
     78                                  self.__get_dynamic_attr('feed_url', obj)), 
     79            'author_name' : self.__get_dynamic_attr('author_name', obj), 
     80            'author_link' : self.__get_dynamic_attr('author_link', obj), 
     81            'author_email' : self.__get_dynamic_attr('author_email', obj), 
     82            'categories' : self.__get_dynamic_attr('categories', obj), 
     83            'feed_copyright' : self.__get_dynamic_attr('feed_copyright', obj), 
     84            'feed_guid' : self.__get_dynamic_attr('feed_guid', obj), 
     85            'ttl' : self.__get_dynamic_attr('ttl', obj), 
     86            } 
     87 
     88    def get_item_kwargs(self, item): 
     89        """ 
     90        Returns the keyword arguments to pass to the `add_item` method of the 
     91        `SyndicationFeed` instance (specified by the `feed_type` attribute). 
     92        """ 
     93        link = add_domain(self.current_site.domain, self.__get_dynamic_attr('item_link', item)) 
     94        enc = None 
     95        enc_url = self.__get_dynamic_attr('item_enclosure_url', item) 
     96        if enc_url: 
     97            enc = feedgenerator.Enclosure( 
     98                url = smart_unicode(enc_url), 
     99                length = smart_unicode(self.__get_dynamic_attr('item_enclosure_length', item)), 
     100                mime_type = smart_unicode(self.__get_dynamic_attr('item_enclosure_mime_type', item)) 
     101                ) 
     102        author_name = self.__get_dynamic_attr('item_author_name', item) 
     103        if author_name is not None: 
     104            author_email = self.__get_dynamic_attr('item_author_email', item) 
     105            author_link = self.__get_dynamic_attr('item_author_link', item) 
     106        else: 
     107            author_email = author_link = None 
     108 
     109        pubdate = self.__get_dynamic_attr('item_pubdate', item) 
     110        if pubdate: 
     111            now = datetime.now() 
     112            utcnow = datetime.utcnow() 
     113 
     114            # Must always subtract smaller time from larger time here. 
     115            if utcnow > now: 
     116                sign = -1 
     117                tzDifference = (utcnow - now) 
     118            else: 
     119                sign = 1 
     120                tzDifference = (now - utcnow) 
     121 
     122            # Round the timezone offset to the nearest half hour. 
     123            tzOffsetMinutes = sign * ((tzDifference.seconds / 60 + 15) / 30) * 30 
     124            tzOffset = timedelta(minutes=tzOffsetMinutes) 
     125            pubdate = pubdate.replace(tzinfo=FixedOffset(tzOffset)) 
     126 
     127        return {'title' : self.title_tmp.render(RequestContext(self.request, {'obj': item, 'site': self.current_site})), 
     128                'link' : link, 
     129                'description' : self.description_tmp.render(RequestContext(self.request, {'obj': item, 'site': self.current_site})), 
     130                'unique_id' : self.__get_dynamic_attr('item_guid', item, link), 
     131                'enclosure' : enc, 
     132                'pubdate' : pubdate, 
     133                'author_name' : author_name, 
     134                'author_email' : author_email, 
     135                'author_link' : author_link, 
     136                'categories' : self.__get_dynamic_attr('item_categories', item), 
     137                'item_copyright' : self.__get_dynamic_attr('item_copyright', item), 
     138                } 
     139 
    65140    def get_feed(self, url=None): 
    66141        """ 
    67142        Returns a feedgenerator.DefaultFeed object, fully populated, for 
     
    77152        except ObjectDoesNotExist: 
    78153            raise FeedDoesNotExist 
    79154 
     155        # Getting the current site. 
    80156        if Site._meta.installed: 
    81             current_site = Site.objects.get_current() 
     157            self.current_site = Site.objects.get_current() 
    82158        else: 
    83             current_site = RequestSite(self.request) 
    84          
    85         link = self.__get_dynamic_attr('link', obj) 
    86         link = add_domain(current_site.domain, link) 
     159            self.current_site = RequestSite(self.request) 
    87160 
    88         feed = self.feed_type( 
    89             title = self.__get_dynamic_attr('title', obj), 
    90             subtitle = self.__get_dynamic_attr('subtitle', obj), 
    91             link = link, 
    92             description = self.__get_dynamic_attr('description', obj), 
    93             language = settings.LANGUAGE_CODE.decode(), 
    94             feed_url = add_domain(current_site.domain, 
    95                                   self.__get_dynamic_attr('feed_url', obj)), 
    96             author_name = self.__get_dynamic_attr('author_name', obj), 
    97             author_link = self.__get_dynamic_attr('author_link', obj), 
    98             author_email = self.__get_dynamic_attr('author_email', obj), 
    99             categories = self.__get_dynamic_attr('categories', obj), 
    100             feed_copyright = self.__get_dynamic_attr('feed_copyright', obj), 
    101             feed_guid = self.__get_dynamic_attr('feed_guid', obj), 
    102             ttl = self.__get_dynamic_attr('ttl', obj), 
    103         ) 
     161        # Initializing the feed. 
     162        feed = self.feed_type(**self.get_feed_kwargs(obj)) 
    104163 
     164        # Getting instances of the title and description templates. 
    105165        try: 
    106             title_tmp = loader.get_template(self.title_template_name) 
     166            self.title_tmp = loader.get_template(self.title_template_name) 
    107167        except TemplateDoesNotExist: 
    108             title_tmp = Template('{{ obj }}') 
     168            self.title_tmp = Template('{{ obj }}') 
    109169        try: 
    110             description_tmp = loader.get_template(self.description_template_name) 
     170            self.description_tmp = loader.get_template(self.description_template_name) 
    111171        except TemplateDoesNotExist: 
    112             description_tmp = Template('{{ obj }}') 
     172            self.description_tmp = Template('{{ obj }}') 
    113173 
     174        # Creating the entry for each item. 
    114175        for item in self.__get_dynamic_attr('items', obj): 
    115             link = add_domain(current_site.domain, self.__get_dynamic_attr('item_link', item)) 
    116             enc = None 
    117             enc_url = self.__get_dynamic_attr('item_enclosure_url', item) 
    118             if enc_url: 
    119                 enc = feedgenerator.Enclosure( 
    120                     url = smart_unicode(enc_url), 
    121                     length = smart_unicode(self.__get_dynamic_attr('item_enclosure_length', item)), 
    122                     mime_type = smart_unicode(self.__get_dynamic_attr('item_enclosure_mime_type', item)) 
    123                 ) 
    124             author_name = self.__get_dynamic_attr('item_author_name', item) 
    125             if author_name is not None: 
    126                 author_email = self.__get_dynamic_attr('item_author_email', item) 
    127                 author_link = self.__get_dynamic_attr('item_author_link', item) 
    128             else: 
    129                 author_email = author_link = None 
    130  
    131             pubdate = self.__get_dynamic_attr('item_pubdate', item) 
    132             if pubdate: 
    133                 now = datetime.now() 
    134                 utcnow = datetime.utcnow() 
    135  
    136                 # Must always subtract smaller time from larger time here. 
    137                 if utcnow > now: 
    138                     sign = -1 
    139                     tzDifference = (utcnow - now) 
    140                 else: 
    141                     sign = 1 
    142                     tzDifference = (now - utcnow) 
    143  
    144                 # Round the timezone offset to the nearest half hour. 
    145                 tzOffsetMinutes = sign * ((tzDifference.seconds / 60 + 15) / 30) * 30 
    146                 tzOffset = timedelta(minutes=tzOffsetMinutes) 
    147                 pubdate = pubdate.replace(tzinfo=FixedOffset(tzOffset)) 
    148  
    149             feed.add_item( 
    150                 title = title_tmp.render(RequestContext(self.request, {'obj': item, 'site': current_site})), 
    151                 link = link, 
    152                 description = description_tmp.render(RequestContext(self.request, {'obj': item, 'site': current_site})), 
    153                 unique_id = self.__get_dynamic_attr('item_guid', item, link), 
    154                 enclosure = enc, 
    155                 pubdate = pubdate, 
    156                 author_name = author_name, 
    157                 author_email = author_email, 
    158                 author_link = author_link, 
    159                 categories = self.__get_dynamic_attr('item_categories', item), 
    160                 item_copyright = self.__get_dynamic_attr('item_copyright', item), 
    161             ) 
     176            feed.add_item(**self.get_item_kwargs(item)) 
    162177        return feed