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:

  1. ¿Cómo genero la consulta para que coincida con la latitud y cómo la devuelvo a la plantilla?
  2. ¿Cómo verifico, por ejemplo, un área de 2 km2 alrededor de esa área?

¿Hay paquetes django para esto?

4
Newtt 2 sep. 2014 a las 16:48

3 respuestas

La mejor respuesta

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

7
Community 23 may. 2017 a las 12:17

Sí, hay un paquete / proyecto para este Geodjango. Puede leer la documentación oficial aquí.

0
José Ricardo Pla 2 sep. 2014 a las 13:17

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

1
coldmind 2 sep. 2014 a las 13:18