This is a pre-production deployment of Warehouse. Changes made here affect the production instance of PyPI (pypi.python.org).
Help us improve Python packaging - Donate today!
Project Description

Introduction

This product helps integrating the collective.geo.* packages and aims to provide some sensible defaults. Besides some integration glue it defines a new interface IGeocodableLocation that can be used to create adapters that knows how to represent the location of a content type with address-like fields as a string suitable for passing to a geocoding API.

Purpose

  • Automatic geocoding of IGeoreferenceable content types via an IGeocodableLocation adapter
  • Caching of geocoding responses
  • Only trigger geocoding lookups if location related fields on the content item changed
  • Facilitate doing automatic geocoding based on location fields and still allow for manually setting custom coordinates

Usage

Automatically geocoding your content types

In order for your content types to be automatically geocoded on ObjectEdited or ObjectInitialized events, you need to create an adapter for your content type that implements IGeocodableLocation and knows how to build a geocodable location string from the content type’s location related fields.

In order to implement the interface you need to define a getLocationString method on your adapter that returns the complete location as a comma separated string, with the location parts getting less specific from left to right.

For example:

'1600 Amphitheatre Parkway, Mountain View, CA, US'
'Engehaldestr. 53, 3012 Bern, Switzerland'

If the getLocationString method returns the empty string or None, the event handler won’t attempt to do a geocode lookup, so this is the suggested way to abort geocoding if not enough location information is available.

Example code:

from ftw.geo.interfaces import IGeocodableLocation
from zope.component import adapts
from zope.interface import implements


class MyTypeLocationAdapter(object):
    """Adapter that is able to represent the location of an MyType in
    a geocodable string form.
    """
    implements(IGeocodableLocation)
    adapts(IMyType)

    def __init__(self, context):
        self.context = context

    def getLocationString(self):
        """Build a geocodable location string from the MyType's address
        related fields.
        """
        street = self.context.getAddress()
        zip_code = self.context.getZip()
        city = self.context.getCity()
        country = self.context.getCountry()

        location = ', '.join([street, zip_code, city, country])
        return location

Register the adapter with ZCML:

<adapter
    factory=".mytpe.MyTypeLocationAdapter"
    />

Caching of geocoding responses

Responses from the geocoding API are being RAM cached. The cache key being used is the result of the getLocationString method, which means that for every unique location string the geocoding lookup is only done once and subsequently fetched from the cache.

Only triggering geocoding when location fields changed

If we were to do a geocode lookup on every ObjectEdited event, any custom coordinates that have been set would be overriden every time any field on the content item is changed (even if the geocoding response itself was fetched from the cache).

To avoid this, ftw.geo stores the result of getLocationString as an annotation on the object and on ObjectEdited checks if the location string (and therefore the location related fields) actually changed, and only does the lookup when necessary. This means:

On ObjectInitialized the content type will first be geocoded initally (unless getLocationString returned None or the empty string). If you manually set coordinates after that through the ‘Coordinates’ tab provided by collective.geo.contentlocations they will be saved and overwrite the coordinates determined previously by geocoding. After that, if you edit the content item and change any fields not related to the location, the custom coordinates will be preserved. Only if you change one of the location related fields used in getLocationString the geocoding will be performed again and any custom coordinates overwritten.

Google API Key

Google’s geocoding API can be used without an API Key, but then is limited to 2500 requests per day. If you defined your Google Maps API Key in collective.geo.settings it will be used, otherwise the geocoding API will be called without an API key.

Rendering a content map viewlet in a custom template

If you don’t want your content map displayed in one of the default viewlet managers (plone.abovecontentbody / plone.abovecontentbody) on the content item’s main view but instead in a custom view and/or a different viewlet manager, this is how you do it:

First, you need to make sure your browser view implements a specific interface and provide a KMLMapViewletLayer adapter (view, request, context, widget) for it:

<adapter
    for="..interfaces.IContactView
         zope.interface.Interface
         zope.interface.Interface
         zope.interface.Interface"
    factory="collective.geo.kml.browser.viewlets.KMLMapViewletLayers"
    />

Your view class have to provide the collective.geo.kml.interfaces.IKMLOpenLayersView:

from collective.geo.kml.interfaces import IKMLOpenLayersView
from Products.Five.browser import BrowserView
from zope.interface import implements


class ContactView(BrowserView):
    implements(IKMLOpenLayersView)

Then, in your view’s template, simply use the macros provided by collective.geo.mapwidget:

<div id="kml-content-viewlet">
  <metal:use use-macro="context/@@collectivegeo-macros/openlayers" />
  <metal:use use-macro="context/@@collectivegeo-macros/map-widget" />
</div>

Dependencies

collective.geo.settings

collective.geo.openlayers

collective.geo.geographer

collective.geo.contentlocations

collective.geo.kml

If you’re having trouble installing the collective.geo.* dependencies (namely libgeos and shapely) trough your distribution’s package manager, you can build them yourself using this buildout configuration:

shapely.cfg:

[buildout]
parts +=
    geos
    shapely

[geos]
recipe = zc.recipe.cmmi
url = http://download.osgeo.org/geos/geos-3.3.5.tar.bz2
md5sum = 2ba61afb7fe2c5ddf642d82d7b16e75b
extra_options =
    CC='gcc -m32'
    CXX='g++ -m32'

[shapely]
recipe = zc.recipe.egg:custom
egg = Shapely
include-dirs = ${geos:location}/include
library-dirs = ${geos:location}/lib
rpath = ${geos:location}/lib

Use it in your main buildout.cfg like this:

[buildout]
extends =
#   ...
    shapely.cfg

[instance1]
eggs +=
    ${shapely:egg}

environment-vars +=
    LD_LIBRARY_PATH ${geos:location}/lib

Contributors

  • Lukas Graf [lukasg], Author

Changelog

1.3.5 (2016-09-29)

  • Fix German translation. [mbaechtold]

1.3.4 (2016-03-30)

  • Fix bug when using ftw.geo in combination with the IReferenceable behavior. This bug will appear with plone >= 4.3.8 [elioschmutz]

1.3.3 (2016-03-30)

  • Fix removing coordinates if no location is given. If you remove an existing address from an object, the handler is now removing the coordinates too. This causes that the map will no longer be visible on the object. [elioschmutz]
  • Restrict versions of some dependencies so they don’t pull in Plone 5. [mbaechtold]

1.3.2 (2014-10-20)

  • Declare plone.app.dexterity as dependency. Dexterity is used in the handlers.py. [mathias.leimgruber]

1.3.1 (2014-10-20)

  • Use Archetypes events for AT content and zope.lifecycle events for DX.
  • BugFix: No longer cast geocode (of geocoders.GoogleV3) to list. It’s already a list. [mathias.leimgruber]

1.3 (2013-11-26)

  • Use conditional imports to account for API changes in geopy 0.96. [lgraf]
  • Use zope.lifecycleevents for dexterity support. [jone]
  • Added missing dependency. [Julian Infanger]

1.2 (2013-05-10)

  • Fix German translation file. [jone]
  • Fix UnicodeDecode error while rendering the portal message for GQueryError.

1.1 (2013-04-03)

  • Use message IDs and defaults in error message translations. [lgraf]
  • Improved exception handling when doing geocoding on save. Deal with network errors and any other unhandled exception, and display meaningful messages for all cases. [lgraf]
  • Fix tests according to the new features [mathias.leimgruber]
  • Display a status message when automatic geocoding didn’t yield any results. [lgraf]
  • Make sure to import exceptions we check for from the googlev3 geocoder after switching to V3 geocoding API. [lgraf]
  • Deal with multiple results for automatic geocoding. When automatic geocoding on save for a content item results in more than one match, choose the first one and display a message to the user that he might want to change it. [lgraf]
  • Remove api key usage. The geopy GoogleV3 Geocoder does not implement an api key. [mathias.leimgruber]
  • Use google map api V3 of geopy 0.95. See -> http://plone.293351.n2.nabble.com/collective-geo-GBadKeyError-when-geocoding-w-geopy-td7563845.html [mathias.leimgruber]

1.0 (2012-12-03)

  • Added import step to uninstall Products.Maps using quickinstaller. [lukasg]
  • First implementation. [lukasg]
Release History

Release History

1.3.5

This version

History Node

TODO: Figure out how to actually get changelog content.

Changelog content for this version goes here.

Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Show More

1.3.4

History Node

TODO: Figure out how to actually get changelog content.

Changelog content for this version goes here.

Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Show More

1.3.3

History Node

TODO: Figure out how to actually get changelog content.

Changelog content for this version goes here.

Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Show More

1.3.2

History Node

TODO: Figure out how to actually get changelog content.

Changelog content for this version goes here.

Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Show More

1.3.1

History Node

TODO: Figure out how to actually get changelog content.

Changelog content for this version goes here.

Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Show More

1.3

History Node

TODO: Figure out how to actually get changelog content.

Changelog content for this version goes here.

Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Show More

1.2

History Node

TODO: Figure out how to actually get changelog content.

Changelog content for this version goes here.

Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Show More

1.1

History Node

TODO: Figure out how to actually get changelog content.

Changelog content for this version goes here.

Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Show More

1.0

History Node

TODO: Figure out how to actually get changelog content.

Changelog content for this version goes here.

Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Show More

Download Files

Download Files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

File Name & Checksum SHA256 Checksum Help Version File Type Upload Date
ftw.geo-1.3.5.tar.gz (23.7 kB) Copy SHA256 Checksum SHA256 Source Sep 29, 2016

Supported By

WebFaction WebFaction Technical Writing Elastic Elastic Search Pingdom Pingdom Monitoring Dyn Dyn DNS Sentry Sentry Error Logging CloudAMQP CloudAMQP RabbitMQ Heroku Heroku PaaS Kabu Creative Kabu Creative UX & Design Fastly Fastly CDN DigiCert DigiCert EV Certificate Rackspace Rackspace Cloud Servers DreamHost DreamHost Log Hosting