def __init__(self, *args, **kwargs): super(SitegeistView, self).__init__(*args, **kwargs) self._geocache = CoordinateCache("view-%s" % self.namespace)
class SitegeistView(View): namespace = None def __init__(self, *args, **kwargs): super(SitegeistView, self).__init__(*args, **kwargs) self._geocache = CoordinateCache("view-%s" % self.namespace) def load_data(self, request, coords, **args): """ Load the data dict needed by this view. Subclasses should implement this method. """ raise NotImplementedError("subclass and implement load_data()") def get_template(self): return "sitegeist/panes/%s.html" % self.namespace def _base_response(self, coords): return {"geo": {"ll": [coords.lat, coords.lon], "boundaries": coords}, "data": {}} def _get_bounds(self, request, param="cll"): """ Get coordinates from the HTTP request. The only supported method is via lat and lon querystring params. """ cll = request.GET.get(param) # set default of Sunlight offices lat = DEFAULT_CLL[0] lon = DEFAULT_CLL[1] if cll and LLFORMAT.match(cll): (lat, lon) = cll.split(",") coords = (lat, lon) bounds = boundary_cache.get(coords) if not bounds: bounds = Geo() bounds.lat = lat bounds.lon = lon pt = "POINT(%s %s)" % (lon, lat) for boundary in Boundary.objects.filter(shape__contains=pt): bounds[boundary.set_name].append(boundary.as_dict()) if bounds: boundary_cache.set(coords, bounds) return bounds def _get_response_type(self, request): """ Get the type of response needed by the client. The only supported method for JSON (at this time) is via the HTTP_X_REQUESTED_WITH header with a value of XMLHttpRequest. I lied, you can also pass format=json as a query string param. """ return "json" if request.is_ajax() or request.GET.get("format") == "json" else "html" def get(self, request, **args): """ Process GET request. Defers to the subclass's load_data() method if cached data is not found. """ # get values from response response_type = self._get_response_type(request) bounds = self._get_bounds(request) if bounds: coords = (float(bounds.lat), float(bounds.lon)) logger.debug("attempting cache read width (%s, %s)" % coords) data = self._geocache.get(coords) if not data: # if data is not cached, load it and cache it logger.debug("cache miss, calling load_data()") data = self.load_data(request, bounds, **args) self._geocache.set(coords, data) else: logger.debug("cache hit!!!!") else: coords = None data = {"data": {}} # response rendering if response_type == "html": context = { "coords": coords, "data": data["data"], "vertical_offset": request.GET.get("vo"), "namespace": self.namespace, "show_header": request.GET.get("header") != "0", } return render(request, self.get_template(), context) return HttpResponse(json.dumps(data), content_type="application/json")
class SitegeistView(View): namespace = None def __init__(self, *args, **kwargs): super(SitegeistView, self).__init__(*args, **kwargs) self._geocache = CoordinateCache("view-%s" % self.namespace) def load_data(self, request, coords, **args): """ Load the data dict needed by this view. Subclasses should implement this method. """ raise NotImplementedError("subclass and implement load_data()") def get_template(self): return "sitegeist/panes/%s.html" % self.namespace def _base_response(self, coords): return { "geo": { "ll": [coords.lat, coords.lon], "boundaries": coords, }, "data": {}, } def _get_bounds(self, request, param='cll'): """ Get coordinates from the HTTP request. The only supported method is via lat and lon querystring params. """ cll = request.GET.get(param) # set default of Sunlight offices lat = DEFAULT_CLL[0] lon = DEFAULT_CLL[1] if cll and LLFORMAT.match(cll): (lat, lon) = cll.split(',') coords = (lat, lon) bounds = boundary_cache.get(coords) if not bounds: bounds = Geo() bounds.lat = lat bounds.lon = lon pt = "POINT(%s %s)" % (lon, lat) for boundary in Boundary.objects.filter(shape__contains=pt): bounds[boundary.set_name].append(boundary.as_dict()) if bounds: boundary_cache.set(coords, bounds) return bounds def _get_response_type(self, request): """ Get the type of response needed by the client. The only supported method for JSON (at this time) is via the HTTP_X_REQUESTED_WITH header with a value of XMLHttpRequest. I lied, you can also pass format=json as a query string param. """ return 'json' if request.is_ajax() or request.GET.get( 'format') == 'json' else 'html' def get(self, request, **args): """ Process GET request. Defers to the subclass's load_data() method if cached data is not found. """ # get values from response response_type = self._get_response_type(request) bounds = self._get_bounds(request) if bounds: coords = (float(bounds.lat), float(bounds.lon)) logger.debug("attempting cache read width (%s, %s)" % coords) data = self._geocache.get(coords) if not data: # if data is not cached, load it and cache it logger.debug("cache miss, calling load_data()") data = self.load_data(request, bounds, **args) self._geocache.set(coords, data) else: logger.debug("cache hit!!!!") else: coords = None data = {'data': {}} # response rendering if response_type == 'html': context = { 'coords': coords, 'data': data['data'], 'vertical_offset': request.GET.get('vo'), 'namespace': self.namespace, 'show_header': request.GET.get('header') != "0", } return render(request, self.get_template(), context) return HttpResponse(json.dumps(data), content_type="application/json")
from sitegeist.data.epa.models import Site from sitegeist.data.nhgis.models import Tract as NHGISTract from sitegeist.data import darksky, foursquare, wunderground, yelp from sitegeist.cache import CoordinateCache from sitegeist.formatting import dec2num, dec2pct, dec2curr from sitegeist import utils, viz RESPONSE_MIMETYPES = { 'text/html': 'html', 'application/json': 'json', } DEFAULT_RESPONSE_MIMETYPE = 'application/json' DEFAULT_CLL = ("38.906956", "-77.042883") logger = logging.getLogger(__name__) boundary_cache = CoordinateCache("boundaries") LLFORMAT = re.compile(r"^(?P<lat>\-?\d+(\.\d+)?),(?P<lon>\-?\d+(\.\d+)?)$") class Geo(defaultdict): def __init__(self, *args, **kwargs): super(Geo, self).__init__(list, *args, **kwargs) self.lat = None self.lon = None class SitegeistView(View): namespace = None