I've got a django model that has a custom attribute called 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 string of format latitude, longitude
. From my template, I pass a url as follows: /nearby?lat='+somevalue+'&long='+somevalue
Now, I want to return nearby entries from List
depending on the values that are passed.
For this I've written a views.py function as follows:
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've done, first_query
returns all entries that start with the same latitude
. However, now I also want to match the longitude
which is why I'm running that for loop
and searching for the index of the comma that separates latitude,longitude
in my LocationField
. n_string
takes the substring of the LocationField
and I'm planning to then match it to my longitude
variable.
My question is two part:
Are there django packages for this?
There are at least 3 ways to do that:
a) Haersine distance (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) use of 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 about circle inscribed in square)
see here my answer: How to filter a django model with latitude and longitude coordinates that fall within a certain radius
You should use GIS-databases for storing and performing operations on coordinates, searching and so on.
For storing location use https://docs.djangoproject.com/en/dev/ref/contrib/gis/model-api/#pointfield
As 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 nearby you should use distance lookups, see examples at https://docs.djangoproject.com/en/dev/ref/contrib/gis/db-api/#distance-lookups
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With