2009-12-05 127 views
2

我想实现基于经度和使用Django和Postgresql的邻近搜索。这是我拥有的模型的抽象版本。Django模型属性地理距离

class Item(models.Model): 
"""docstring for Item""" 
uuid = UUIDField(primary_key=True, auto=True) 
name = models.CharField(_("name"), max_length=200) 
address = models.CharField(_('street address'), max_length=255, blank=True, null=True) 
location = models.CharField(_('location'), max_length=40, blank=True, null=True) 

@property 
def geo_distance(self, location=None): 
    if location is not None: 
     cursor = connection.cursor() 
     cursor.execute("SELECT geo_distance(CAST('%s')) AS POINT, CAST('%s') AS POINT)" % 
      self.location, location) 
     return round(float(cursor.fetchone() * 1.621371192237), 2) 

我希望能够做这样的事情在views.py:

items = Item.objects.filter(name__istartwith="Anything") 
results = [] 
for item in items: 
    results.append({ 
     'name': item.name, 
     'distance': item.geo_distance("(11.23123, -12.123213)") 
    }) 

我知道这是不是最好的方法。欢迎任何建议。

+2

你可能想用geodjango和geopy来标记它。 – 2009-12-06 00:07:01

回答

2

如果你基于经纬度搜索,我会建议你GeoDjango。要计算从X点开始的两点或周围区域之间的距离,可以使用Haversine formula。最好使用procedure来编写距离计算。据我所知,Django不支持创建程序,我在计算距离方面做了一些基准测试,我发现程序更快,而不是在Django端进行计算。祝你好运。

+1

感谢Prashanth的建议。我一定会深入研究GeoDjango。就目前而言,我使用了Geopy来解决我的问题。其地理编码和距离计算模块相当有用。 – Nav 2009-12-07 02:23:43

1

那么,你的代码并不可怕。我想你是关心性能的,因为item.geo_distance()在iteration中执行?这并不重要,这将不得不在一段时间内计算。您的解决方案是好的,但这里有一些其他指针:

  • 使用geopy(或GeoDjango内置)
  • 务必在源(数据库)来过滤数据。

关于第二点,过滤你的数据。我看到你正在过滤名称,这意味着你没有使用过滤距离。如果你确实想使用距离某个点的距离作为过滤器(例如,不超过40英里),那么你会遇到geopy和geodjango可以提供帮助的一些新问题。这里常见的解决方案是近似距离(以平方为单位),根据此近似值过滤数据,然后计算精确距离。

+0

感谢marcc花时间。 Geopy似乎是我需要的,我已经将它融入到我的项目中。 我忘了将geo_distance作为过滤器,但这是其中一个要求。我使用Geopy的距离计算模块完成了这项工作。与Geopy相比,在数据库级别对其进行过滤似乎不准确,而且速度比几百毫秒慢。 – Nav 2009-12-07 02:35:11

+0

不错!几个月前,我完成了一个django/geopy项目。使用geopy计算来为iPhone应用程序使用的API提供动力。奇迹般有效。 – marcc 2009-12-07 05:53:50