Django

Code

Ticket #6547: georss_syndication_patch_v4.diff

File georss_syndication_patch_v4.diff, 7.3 kB (added by jbronn, 5 months ago)

Less intrusive patch to contrib.syndication.

  • 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 
     4class GeoFeedMixin(object): 
     5    w3c_geo = False 
     6 
     7    def georss_coords(self, coords): 
     8        """ 
     9        In GeoRSS coordinate pairs are ordered by lat/lon and separated by 
     10        a single white space.  Given a tuple of coordinates, this will return 
     11        a unicode GeoRSS representation. 
     12        """ 
     13        return u' '.join([u'%f %f' % (coord[1], coord[0]) for coord in coords]) 
     14 
     15    def add_georss_point(self, handler, coords): 
     16        """ 
     17        Adds a GeoRSS point with the given coords using the given handler. 
     18        Handles the differences between simple GeoRSS and the more pouplar 
     19        W3C Geo specification. 
     20        """ 
     21        if self.w3c_geo: 
     22            lon, lat = coords[:2] 
     23            handler.addQuickElement(u'geo:lat', u'%f' % lat) 
     24            handler.addQuickElement(u'geo:lon', u'%f' % lon) 
     25        else: 
     26            handler.addQuickElement(u'georss:point', self.georss_coords((coords,))) 
     27 
     28    def add_georss_element(self, handler, item): 
     29        """ 
     30        This routine adds a GeoRSS XML element using the given item and handler. 
     31        """ 
     32        # Getting the Geometry object. 
     33        geom = item.get('geometry', None) 
     34        if not geom is None: 
     35            if isinstance(geom, (list, tuple)): 
     36                # Special case if a tuple/list was passed in.  The tuple may be 
     37                # a point or a box 
     38                box_coords = None 
     39                if isinstance(geom[0], (list, tuple)): 
     40                    # Box: ( (X0, Y0), (X1, Y1) ) 
     41                    if len(geom) == 2: 
     42                        box_coords = geom 
     43                    else: 
     44                        raise ValueError('Only should be two sets of coordinates.') 
     45                else: 
     46                    if len(geom) == 2: 
     47                        # Point: (X, Y) 
     48                        self.add_georss_point(handler, geom) 
     49                    elif len(geom) == 4: 
     50                        # Box: (X0, Y0, X1, Y1) 
     51                        box_coords = (geom[:2], geom[2:]) 
     52                    else: 
     53                        raise ValueError('Only should be 2 or 4 numeric elements.') 
     54                # If a GeoRSS box was given via tuple. 
     55                if not box_coords is None: 
     56                    if self.w3c_geo: raise ValueError('Cannot use simple GeoRSS box in W3C Geo feeds.') 
     57                    handler.addQuickElement(u'georss:box', self.georss_coords(box_coords)) 
     58            else: 
     59                # Getting the lower-case geometry type. 
     60                gtype = str(geom.geom_type).lower() 
     61              
     62                if gtype == 'point': 
     63                    self.add_georss_point(handler, geom.coords)  
     64                else: 
     65                    if self.w3c_geo: raise TypeError('W3C Geo only supports Point geometries.') 
     66                    # For formatting consistent w/the GeoRSS simple standard: 
     67                    # http://georss.org/1.0#simple 
     68                    if gtype in ('linestring', 'linearring'): 
     69                        handler.addQuickElement(u'georss:line', self.georss_coords(geom.coords)) 
     70                    elif gtype in ('polygon',): 
     71                        # Only support the exterior ring. 
     72                        handler.addQuickElement(u'georss:polygon', self.georss_coords(geom[0].coords)) 
     73                    else: 
     74                        raise TypeError('Geometry type "%s" not supported.' % geom.geom_type) 
     75 
     76### SyndicationFeed subclasses ### 
     77class W3CGeoFeed(Rss201rev2Feed, GeoFeedMixin): 
     78    w3c_geo = True 
     79 
     80    def rss_attributes(self): 
     81        attrs = super(W3CGeoFeed, self).rss_attributes() 
     82        attrs[u'xmlns:geo'] = u'http://www.w3.org/2003/01/geo/wgs84_pos#' 
     83        return attrs 
     84 
     85    def add_item_elements(self, handler, item): 
     86        super(W3CGeoFeed, self).add_item_elements(handler, item) 
     87        self.add_georss_element(handler, item) 
     88 
     89    def add_root_elements(self, handler): 
     90        super(W3CGeoFeed, self).add_root_elements(handler) 
     91        self.add_georss_element(handler, self.feed) 
     92 
     93class GeoRSSFeed(Rss201rev2Feed, GeoFeedMixin): 
     94    def rss_attributes(self): 
     95        attrs = super(GeoRSSFeed, self).rss_attributes() 
     96        attrs[u'xmlns:georss'] = u'http://www.georss.org/georss' 
     97        return attrs 
     98 
     99    def add_item_elements(self, handler, item): 
     100        super(GeoRSSFeed, self).add_item_elements(handler, item) 
     101        self.add_georss_element(handler, item) 
     102 
     103    def add_root_elements(self, handler): 
     104        super(GeoRSSFeed, self).add_root_elements(handler) 
     105        self.add_georss_element(handler, self.feed) 
     106 
     107class GeoAtom1Feed(Atom1Feed, GeoFeedMixin): 
     108    def root_attributes(self): 
     109        attrs = super(GeoAtom1Feed, self).root_attributes() 
     110        attrs[u'xmlns:georss'] = u'http://www.georss.org/georss' 
     111        return attrs 
     112 
     113    def add_item_elements(self, handler, item): 
     114        super(GeoAtom1Feed, self).add_item_elements(handler, item) 
     115        self.add_georss_element(handler, item) 
     116 
     117    def add_root_elements(self, handler): 
     118        super(GeoAtom1Feed, self).add_root_elements(handler) 
     119        self.add_georss_element(handler, self.feed) 
     120         
     121class Feed(BaseFeed): 
     122    """ 
     123    This is a subclass of the `Feed` from `django.contrib.syndication`. 
     124    This allows users to define a `geometry(obj)` and/or `item_geometry(item)` 
     125    methods on their own subclasses so that geo-referenced information may 
     126    placed in the feed. 
     127    """ 
     128    feed_type = GeoRSSFeed 
     129 
     130    def feed_extra_kwargs(self, obj): 
     131        return {'geometry' : self.__get_dynamic_attr('geometry', obj)} 
     132 
     133    def item_extra_kwargs(self, item): 
     134        return {'geometry' : self.__get_dynamic_attr('item_geometry', item)} 
  • django/contrib/syndication/feeds.py

    old new  
    5959                return attr() 
    6060        return attr 
    6161 
     62    def feed_extra_kwargs(self, obj): 
     63        """ 
     64        Returns an extra keyword arguments dictionary that is used when 
     65        initializing the feed generator. 
     66        """ 
     67        return {} 
     68 
     69    def item_extra_kwargs(self, item): 
     70        """ 
     71        Returns an extra keyword arguments dictionary that is used with 
     72        the `add_item` call of the feed generator. 
     73        """ 
     74        return {} 
     75 
    6276    def get_object(self, bits): 
    6377        return None 
    6478 
     
    100114            feed_copyright = self.__get_dynamic_attr('feed_copyright', obj), 
    101115            feed_guid = self.__get_dynamic_attr('feed_guid', obj), 
    102116            ttl = self.__get_dynamic_attr('ttl', obj), 
     117            **self.feed_extra_kwargs(obj) 
    103118        ) 
    104119 
    105120        try: 
     
    158173                author_link = author_link, 
    159174                categories = self.__get_dynamic_attr('item_categories', item), 
    160175                item_copyright = self.__get_dynamic_attr('item_copyright', item), 
     176                **self.item_extra_kwargs(item) 
    161177            ) 
    162178        return feed