In today's world, location-based features are increasingly essential in web applications. Integrating geographic data can significantly enhance user experience, whether finding friends nearby, locating nearby services, or enabling geotagged content.
In this blog, we'll explore how to find nearby users based on their geographical coordinates (latitude and longitude) and a specified radius using Django's ORM.
First, we'll define a Location
model to store each user's geographical coordinates. We'll use Django's built-in User model to associate each location with a user.
from django.db import models
from django.contrib.auth.models import User
class Location(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
latitude = models.DecimalField(max_digits=9, decimal_places=6, db_index=True)
longitude = models.DecimalField(max_digits=9, decimal_places=6, db_index=True)
def __str__(self):
return str(self.user)
user: A ForeignKey linking to Django's User model. This establishes a relationship where each user can have one or more locations.
latitude & longitude: DecimalField fields storing the geographical coordinates with precision up to six decimal places, which is sufficient for most location-based applications.
Implementing the Haversine Formula in Django
The Haversine formula
is a widely used mathematical equation that calculates the great-circle distance between two points on the Earth’s surface, with latitudes and longitudes. This formula is especially useful in navigation, geofencing, geospatial analysis, and location-based services over the Earth's surface.
Here's the function with the Haversine formula
integrated into the Location
model to fetch users within a specified radius using Django ORM:
from django.db.models import F, Value
from django.db.models.functions import ACos, Cos, Radians, Sin
class Location(models.Model):
# ... [fields as above] ...
@classmethod
def get_users_within_radius(cls, center_latitude, center_longitude, radius_km):
# Haversine formula to calculate distances
distance_expression = (
ACos(
Sin(Radians(F('latitude'))) * Sin(Radians(Value(center_latitude))) +
Cos(Radians(F('latitude'))) * Cos(Radians(Value(center_latitude))) *
Cos(Radians(F('longitude')) - Radians(Value(center_longitude)))
) * 6371 # Earth's radius in kilometers
)
# Filter users within the specified radius
users_within_radius = cls.objects.annotate(
distance=distance_expression
).filter(
distance__lte=radius_km
).select_related('user')
return users_within_radius
This method calculates distances using the
Haversine formula
and filters users within the given radius.
Fetching Users Within a Specified Radius
With the get_users_within_radius
method in place, fetching nearby users becomes straightforward. Here's how you can use it:
from .models import Location
# Kathmandu latitude and longitude
center_latitude = 27.707460
center_longitude = 85.312205
radius_km = 10 # 10 kilometers
nearby_location_points = Location.get_users_within_radius(
center_latitude, center_longitude, radius_km
)
nearby_users = [
location.user for location in nearby_location_points
]
Explanation
-
Defining Center Coordinates: Replace
center_latitude
andcenter_longitude
with the desired center point, such as the current user's location. -
Radius Specification: Set
radius_km
to the desired search radius in kilometers. -
Fetching Nearby Locations: Call
get_users_within_radius
to retrieve Location instances within the specified radius. - Extracting Users: Iterate through the Location instances to collect the associated User objects.
Implementing geolocation search in Django is a valuable skill for developers aiming to create location-based services. By understanding the Haversine formula
developers can build efficient location-based search.
For more advanced geographic capabilities, explore GeoDjango and spatial databases.
Top comments (0)