PageRenderTime 41ms CodeModel.GetById 33ms RepoModel.GetById 0ms app.codeStats 0ms

/django/contrib/gis/feeds.py

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