Tengo un modelo de django que tiene un atributo personalizado llamado LocationField
.
class List(models.Model):
id = models.AutoField(primary_key=True)
title = models.CharField(max_length=200)
location = LocationField(blank=True, max_length=255)
Los valores en esto se almacenan como una cadena de formato latitude, longitude
. Desde mi plantilla, paso una url de la siguiente manera: /nearby?lat='+somevalue+'&long='+somevalue
Ahora, quiero devolver entradas cercanas de List
dependiendo de los valores que se pasan.
Para esto, he escrito una función views.py de la siguiente manera:
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:]
Para aclarar lo que he hecho, first_query
devuelve todas las entradas que comienzan con el mismo latitude
. Sin embargo, ahora también quiero hacer coincidir el longitude
, por eso estoy ejecutando ese for loop
y buscando el índice de la coma que separa latitude,longitude
en mi LocationField
. n_string
toma la subcadena de LocationField
y planeo hacerla coincidir con mi variable longitude
.
Mi pregunta es de dos partes:
- ¿Cómo genero la consulta para que coincida con la latitud y cómo la devuelvo a la plantilla?
- ¿Cómo verifico, por ejemplo, un área de 2 km2 alrededor de esa área?
¿Hay paquetes django para esto?
3 respuestas
Hay al menos 3 formas de hacerlo:
a) Distancia de Haersine (ejemplo en 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) uso de 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) algunas consultas inteligentes (piense en un círculo inscrito en un cuadrado)
Mira aquí mi respuesta: Cómo filtrar un modelo django con coordenadas de latitud y longitud que se encuentran dentro de un cierto radio
Sí, hay un paquete / proyecto para este Geodjango. Puede leer la documentación oficial aquí.
Debe usar bases de datos SIG para almacenar y realizar operaciones en coordenadas, búsquedas, etc.
Para almacenar la ubicación, use https: //docs.djangoproject. com / es / dev / ref / contrib / gis / model-api / # pointfield
Como base de datos, puede usar https://docs.djangoproject.com / es / dev / ref / contrib / gis / install / # postgis o https://docs.djangoproject.com/en/dev/ref/contrib/gis/install/spatialite/
Para buscar cerca, debe usar búsquedas de distancia, consulte los ejemplos en https://docs.djangoproject.com/en/dev/ref/contrib/gis/db-api/#distance-lookups
Preguntas relacionadas
Preguntas vinculadas
Nuevas preguntas
python
Python es un lenguaje de programación multipropósito, de tipificación dinámica y de múltiples paradigmas. Está diseñado para ser rápido de aprender, comprender y usar, y hacer cumplir una sintaxis limpia y uniforme. Tenga en cuenta que Python 2 está oficialmente fuera de soporte a partir del 01-01-2020. Aún así, para preguntas de Python específicas de la versión, agregue la etiqueta [python-2.7] o [python-3.x]. Cuando utilice una variante de Python (por ejemplo, Jython, PyPy) o una biblioteca (por ejemplo, Pandas y NumPy), inclúyala en las etiquetas.