如何根据经度和纬度过滤geodjango

use*_*979 4 django geodjango

我有一个存储经度和纬度的应用程序,现在我想将它与 geodjango 集成,应用程序如下所示。

class Location(models.Model):
    #other fields here
    lat = models.CharField(blank=True, max_length=100)
    lng = models.CharField(blank=True, max_length=100)
Run Code Online (Sandbox Code Playgroud)

现在我想根据距离过滤位置,比如使用 django.contrib.gis.measure import D 和 GEOSGeometry 过滤距离 pk = 1 位置 1 公里的所有位置,或者我应该重构模型以具有点而不是经度和纬度,这样我可以做这样的事情:

Location.objects.filter(point__dwithin=(D(km=5)))
Run Code Online (Sandbox Code Playgroud)

任何意见和建议都可以。

e4c*_*4c5 5

架构迁移

快进到 2016 年,我们在 django 中内置了迁移功能,您不再需要向南。您只需要两次迁移,而不是三次。

第一步:更改模型。

class Location(models.Model):
    #other fields here
    lat = models.CharField(blank=True, max_length=100)
    lng = models.CharField(blank=True, max_length=100)

    point = models.PointField(null=True)
Run Code Online (Sandbox Code Playgroud)

第 2 步:创建迁移

./manage.py makemigrations
Run Code Online (Sandbox Code Playgroud)

数据迁移

这是第三步,涉及编辑上面创建的迁移文件,查看操作部分并添加

migrations.RunSQL('''UPDATE myapp_location SET `point` = Point(lat,lng)''')
Run Code Online (Sandbox Code Playgroud)

这个查询是针对mysql的。如果您使用 PostGis 您的查询将是

migrations.RunSQL('''UPDATE myapp_location SET "point" = ST_MakePoint(lng,lat)''')
Run Code Online (Sandbox Code Playgroud)

请注意,postgis 的格式为lng,lat 注意,这是单个查询,执行速度应该相当快。如果你有一百万条记录,用 python 迭代所有行并逐一更新它们就意味着一百万次查询!

步骤4:./manage.py migrate

第 5 步:从模型中删除 lat、lng 列。

第6步:./manage.py makemigrations

第7步:./manage.py migrate

  • 我在实现上述 sql 查询时遇到错误,它引发了“django.db.utils.DataError:几何 SRID (0) 与列 SRID (4326) 不匹配”我通过像这样更新“migrations.RunSQL(”) 解决了它'更新 myapp_location 设置点 = ST_SetSRID(ST_MakePoint(llng,lat),4326)''')` (2认同)