Returning nearby locations to Django
I have a django model with a custom attribute LocationField
.
class List(models.Model):
id = models.AutoField(primary_key=True)
title = models.CharField(max_length=200)
location = LocationField(blank=True, max_length=255)
The values in this are stored as a format string latitude, longitude
. From my template, I am passing the url like this:/nearby?lat='+somevalue+'&long='+somevalue
Now I want to return adjacent records from List
depending on the passed values.
For this, I wrote the views.py function like this:
def nearby(request):
if request.GET['lat']:
lat = request.GET['lat']
longitude = request.GET['long']
first_query = Playlist.objects.filter(location__istartswith=lat)
for f in first_query:
l = f.index(',')
n_string = f[l:]
To clarify what I did, it first_query
returns all records starting with the same latitude
. However, now I also want to match longitude
, so I run this one for loop
and look for the comma index that separates latitude,longitude
in mine LocationField
. n_string
takes a substring LocationField
and I plan on then matching it to my variable longitude
.
My question has two parts:
- How do I create a query to match latitude and how do I return it to the template?
- How can I check, for example, the area of 2 square kilometers around this area?
Are there django packages for this?
source to share
There are at least 3 ways to do this:
a) Distance from Haersine (example in MySQL)
def nearby_spots_old(request, lat, lng, radius=5000, limit=50):
"""
WITHOUT use of any external library, using raw MySQL and Haversine Formula
http://en.wikipedia.org/wiki/Haversine_formula
"""
radius = float(radius) / 1000.0
query = """SELECT id, (6367*acos(cos(radians(%2f))
*cos(radians(latitude))*cos(radians(longitude)-radians(%2f))
+sin(radians(%2f))*sin(radians(latitude))))
AS distance FROM demo_spot HAVING
distance < %2f ORDER BY distance LIMIT 0, %d""" % (
float(lat),
float(lng),
float(lat),
radius,
limit
)
queryset = Spot.objects.raw(query)
serializer = SpotWithDistanceSerializer(queryset, many=True)
return JSONResponse(serializer.data)
b) using Geodjango (PostgreSQL + PostGIS)
def nearby_spots_new(request, lat, lng, radius=5000, limit=50):
"""
WITH USE OF GEODJANGO and POSTGIS
https://docs.djangoproject.com/en/dev/ref/contrib/gis/db-api/#distance-queries
"""
user_location = fromstr("POINT(%s %s)" % (lng, lat))
desired_radius = {'m': radius}
nearby_spots = Spot.objects.filter(
mpoint__distance_lte=(user_location, D(**desired_radius))).distance(
user_location).order_by('distance')[:limit]
serializer = SpotWithDistanceSerializer(nearby_spots, many=True)
return JSONResponse(serializer.data)
c) some smart queries (think of a circle in a square)
see my answer here: How to filter django model with latitude and longitude coordinates that fall within a specific radius
source to share
You must use GIS databases to store and perform operations on coordinates, searches, etc.
To keep using location https://docs.djangoproject.com/en/dev/ref/contrib/gis/model-api/#pointfield
As a database you can use https://docs.djangoproject.com/en/dev/ref/contrib/gis/install/#postgis or https://docs.djangoproject.com/en/dev/ref/contrib/ gis / install / spatialite /
To search for nearby you have to use distance search, see examples at https://docs.djangoproject.com/en/dev/ref/contrib/gis/db-api/#distance-lookups
source to share