2017-07-18 3 views
2

J'essaie de récupérer certains postes en fonction de leur proximité géographique.
Comme vous pouvez le voir dans le code, j'utilise GeoDjango et le code est exécuté dans une vue.
Le problème est que le filtre de distance semble être complètement ignoré. Quand je vérifie les distances sur le jeu de requête, j'obtiens les distances prévues (1m et 18km) mais le poste de 18km ne devrait pas avoir été récupéré.Geodjango requête à distance ne récupérant pas les résultats corrects

def get(self, request, format=None): 
    latlon=request.query_params 
    pnt = GEOSGeometry('SRID=28992;POINT(%s %s)'%(latlon['lat'],latlon['lon'])) 
    posts = Post.objects.filter(point__distance_lte=(pnt, D(km=1))) 
    serialized = PostSerializer(posts, many=True) 
    for post in posts: 
     distance = pnt.distance(post.point) 
     print("Km distance:",distance * 100) 
    return JsonResponse(serialized.data, safe=False) 

Résultat:

Km distance: 0.00015231546206626192 
Km distance: 18.317378752081577 
[18/Jul/2017 13:24:35] "GET /api/posts/?lon=5.8372264&lat=51.8125626 HTTP/1.1" 200 144 

Répondre

1

Je crois que votre problème vient du reverse order of lat and lon dans votre création de points.

Comme une note de côté, je préfère utiliser la méthode Point() pour la création de points:

ptn = Point(x=latlon['lon'], y=latlon['lat'], srid=28992) 

Modifier en raison de ce commentaire:

J'ai essayé initialiseur, il semble correct pour moi merci. Cependant, il ne semble pas avoir résolu le problème. Il ressemble presque à l'unité de distance par défaut est les décamètres, car cela fonctionne correctement. posts = Post.objects.filter(point__distance_lte=(pnt, 0.05)) cette recherche dans un rayon de 5 km - Evan

Depuis ce qui précède ne résout pas votre problème, je suppose que le dwithin's know problem with Distance objects appliquent aux requêtes distance ainsi.

Comme indiqué dans la solution liée ci-dessus, les champs de géométrie sont définis par défaut sur WGS84 avec degrees comme unité de mesure par défaut.

0.05 degrees ~= 5 km, et c'est pourquoi votre solution a fonctionné correctement.

Peut-être que l'équipe de geodjango devrait être informée de cela?

+0

J'ai essayé cet initialiseur, il me semble plus correct de vous remercier. Cependant, il ne semble pas avoir résolu le problème. Il ressemble presque à l'unité de distance par défaut est les décamètres, car cela fonctionne correctement. 'posts = Post.objects.filter (point__distance_lte = (pnt, 0.05)) 'ceci recherche dans une gamme de 5km – Evan

+0

@Evan Comme je vois ici: https://epsg.io/28992, l'unité par défaut est mètres. J'ai édité ma réponse pour inclure une explication possible du problème. –

0

même SRID? J'utilise beaucoup cela, mais avec

source = models.PointField(geography=True, srid=4326) 

puis dans un gestionnaire:

def starts_within_range_of(self, my_start, distance): 
    ret_value = self.filter(
     source__distance_lte=(my_start, distance)) 
    return ret_value 

Mais AllWays avec 4326

+0

Oui, le srid est le même. Je l'ai un peu fait fonctionner mais ce n'est pas très élégant. Cela semble fonctionner 'posts = Post.objects.filter (point__distance_lte = (pnt, mètres * 1e-05))' – Evan

+0

avez-vous essayé: 'pnt = django.contrib.gis.geos.Point (x = 51.8125626, y = 5.8372264, srid = 28992) '? – mbieren

+0

Non je n'ai pas essayé, mais je ne pense pas que le problème est avec le point 'pnt' puisque je l'utilise dans la boucle' for' et il donne de bonnes distances. – Evan