1
votes

What I am trying to do is to implement geospatial search by means of django-haystack. In official guide, they are suggesting to convert from plain float coordinates to django.contrib.gis.geos.Point object. However, in this guide they do not mention how to render Points in templates. When I am trying to do so, I am getting next exception:

 raise SpatialError("Point '%s' doesn't appear to be a GEOS geometry." % geom)
haystack.exceptions.SpatialError: Point 'POINT (49.8448879999999974 40.3779240000000001)' doesn't appear to be a GEOS geometry.

Model class is something like this:

class Shop(models.Model):
    latitude = models.FloatField()
    longitude = models.FloatField()

    def get_location(self):
        return Point(self.latitude, self.longitude)

Index looks like this:

class ShopIndex(indexes.SearchIndex, indexes.Indexable):
    text = indexes.CharField(document=True, use_template=True)
    location = indexes.LocationField(model_attr='get_location', use_template=True)

    def get_model(self):
         return Shop

    def index_queryset(self, using=None):
         return self.get_model().objects.all()

Template for rendering location looks like this:

{{ object.get_location }}

Is there any other way to declare coordinates in template? (so they can be utilized by haystack for geospatial search)? Or maybe any workaround for problem described by exception?

Update

The only place where location is supposed to be used is next search query:

# The point, around which we do want to search
point = Point(lon, lat)
# radius of geospatial search
distance = D(km=rad)

SearchQuerySet().models(models.Location).dwithin('location', point, distance)
1
Not sure if it matters here, but the Point constructor takes longitude as first argument, i.e. Point(self.longitude, self.latitude), so you might be getting errors due to that. - yellowcap
Another try could be to return the geometry already as WKT. Not sure how the templating engine converts the point to wkt. So in your function, could you return Point(self.longitude, self.latitude).wkt? I doubt that this is the problem, but it would be more explicit for what you want. - yellowcap
Also, could you please provide some more of your Template? Where are you using the location, is it to call another function? So if you could expand the template example above by a few lines before and after, it might be easier to understand where the problem is. - yellowcap
In the example from the haystack docs the LocationField does not use the template. Did you try to leave the template part away for that field? - yellowcap
Maybe the template part is not supported for distance lookups. In that case you would need to go for a custom approach such as you describe. - yellowcap

1 Answers

0
votes

You have to convert the Point object into Geo Geometry object. Then modify the get_model method written in search_indexes.py

from django.contrib.gis import geos
def get_location(self):<br>
return geos.fromstr("POINT(%s %s)" %(self.longitude, self.latitude))