Пример #1
0
 def __init__(self, *args, **kwargs):
     super(SitegeistView, self).__init__(*args, **kwargs)
     self._geocache = CoordinateCache("view-%s" % self.namespace)
Пример #2
0
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")
Пример #3
0
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")
Пример #4
0
 def __init__(self, *args, **kwargs):
     super(SitegeistView, self).__init__(*args, **kwargs)
     self._geocache = CoordinateCache("view-%s" % self.namespace)
Пример #5
0
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