Putting it all together, part 3

Now we make our code restrict to things near the user when they allow geolocation…but the results aren’t really what we’re shooting for.

def earthquake_display(request):
    search_origin = False
    if request.GET.get('lat') and request.GET.get('lon'):
        search_origin = Point(float(request.GET.get('lon')), float(request.GET.get('lat')))

    weekago = datetime.datetime.now() - datetime.timedelta(days=7)
    quakes = Quake.objects.filter(datetime__gte=weekago).order_by('-datetime')

    last_check = cache.get('usgs-poll-last-finished', datetime.datetime(2000, 1, 1))
    checking = cache.get('usgs-poll-in-progress', False)
    if not checking:
        cache.set('usgs-poll-in-progress', True)
        latest_quake_ago = datetime.datetime.now() - quakes[0].datetime
        latest_check_ago = datetime.datetime.now() - last_check
        if latest_quake_ago > datetime.timedelta(minutes=90) and latest_check_ago > datetime.timedelta(minutes=90):
            from django.core import management
            management.call_command('load_quakes')
            cache.set('usgs-poll-last-finished', datetime.datetime.now())
            # and refresh the QuerySet to get the new data
            quakes = Quake.objects.filter(datetime__gte=weekago).order_by('-datetime')
        cache.delete('usgs-poll-in-progress')
        checking = False

    if search_origin:
        quakes = quakes.distance(search_origin).order_by('distance', '-datetime')

    quakes = quakes[:25]

    return render_to_response('earthquakes.html', {
        'object_list': quakes,
        'checking': checking,
    }, context_instance=RequestContext(request))
<html>
<head>
  <script src='http://media.adamfast.com/QueryData.compressed.js'></script>
  <script language='JavaScript'>

    function checkLocation() {
      var getData = new QueryData();
      if ('lat' in getData) { }
      else {
        if (navigator.geolocation) {
          navigator.geolocation.getCurrentPosition(
            function (ppos) {
              window.location.href = window.location.href + '?lat=' + ppos.coords.latitude + '&lon=' + ppos.coords.longitude;
            },
            function (err) {
              switch(err.code) {

                case err.TIMEOUT:
                  alert('Attempts to retrieve location timed out.')
                  break;

                case err.POSITION_UNAVAILABLE:
                  alert("Your browser doesn't know where you are.")
                  break;

                case err.PERMISSION_DENIED:
                  alert('You have to give us permission!')
                  break;

                case err.UNKNOWN_ERROR:
                  alert('Unknown error returned.')
                  break;

                default:
                  alert(err + ' ' + err.code)

              }
            }
          );
        }
      }
    }
  </script>
</head>
<body{% block body_override %} onLoad="javascript:checkLocation();"{% endblock body_override %}>
{% block content %}
    {% for object in object_list %}
    {{ object }}<br>
    {% endfor %}
{% endblock content %}
</body>
</html>

This is returning results with too much emphasis on distance and not enough on how long ago the activity at that distance was. So I tried a few things:

  • Restrict to activity only in the past 4 hours instead of a week (not bad! helps quite a bit.)
  • Restrict to activity within 1000 miles (maybe restricts too much? This left me with no results for Missouri where I write this, but there are no quakes recently near here.
Between them I got a pretty usable app. If it can’t find anything, “Nope.” is returned. For now, if anything was found it returns a list. If we wanted we could hook up GeoIP as a fallback, but since I’m playgrounding this on ep.io I don’t have c extensions to use the module and have to call it good with just HTML5.
The “final” view, if you’d like to see it:
def earthquake_display(request):
    search_origin = False
    if request.GET.get('lat') and request.GET.get('lon'):
        search_origin = Point(float(request.GET.get('lon')), float(request.GET.get('lat')))
        search_origin.transform(900913)
        search_poly = search_origin.buffer(1000 * 2172.344)
        search_poly.transform(4326)
        search_origin.transform(4326)

#    weekago = datetime.datetime.now() - datetime.timedelta(days=7)
#    quakes = Quake.objects.filter(datetime__gte=weekago).order_by('-datetime')
    last_4_hrs = datetime.datetime.now() - datetime.timedelta(hours=4)
    quakes = Quake.objects.filter(datetime__gte=last_4_hrs).order_by('-datetime')

    last_check = cache.get('usgs-poll-last-finished', datetime.datetime(2000, 1, 1))
    checking = cache.get('usgs-poll-in-progress', False)
    if not checking:
        cache.set('usgs-poll-in-progress', True)
        latest_quake_ago = datetime.datetime.now() - quakes[0].datetime
        latest_check_ago = datetime.datetime.now() - last_check
        if latest_quake_ago > datetime.timedelta(minutes=90) and latest_check_ago > datetime.timedelta(minutes=90):
            from django.core import management
            management.call_command('load_quakes')
            cache.set('usgs-poll-last-finished', datetime.datetime.now())
            # and refresh the QuerySet to get the new data

#            quakes = Quake.objects.filter(datetime__gte=weekago).order_by('-datetime')
            quakes = Quake.objects.filter(datetime__gte=last_4_hrs).order_by('-datetime')

        cache.delete('usgs-poll-in-progress')
        checking = False

    if search_origin:
        quakes = quakes.filter(point__within=search_origin)
        quakes = quakes.distance(search_origin).order_by('distance', '-datetime')

    quakes = quakes[:10]

    return render_to_response('earthquakes.html', {
        'object_list': quakes,
        'checking': checking,
    }, context_instance=RequestContext(request))

With that we’ve built a small app with a data source, views, templates, and a “real” purpose all the way through. I hope it’s been helpful for several of you and apologize that some things wound up basically just being repeated from earlier topics, but hopefully after the in-depth back then it was easier to walk along as something was built from it.

Leave a Reply

Your email address will not be published. Required fields are marked *