Ticket #6547: georss_syndication_patch_v2.diff

File georss_syndication_patch_v2.diff, 13.0 KB (added by jbronn, 16 years ago)

Version 2; uses W3C Geo for RSS points.

  • django/contrib/gis/feeds.py

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

     
    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
Back to Top