在 GeoDjango 中使用 distance() 时出现数据库错误
给定以下(简化的)模型:
from django.contrib.gis.db import models
class City(models.Model):
center = models.PointField(spatial_index=True, null=True)
objects = models.GeoManager()
class Place(models.Model):
city = models.ForeignKey(City, null=True)
lat = models.FloatField(null=True)
lng = models.FloatField(null=True)
objects = models.GeoManager()
暂时忘记了 Place 中的经纬度应该移动到 PointField() ,我试图查看所有的地点 code> 并找到最近的城市。目前,我正在做:
from django.contrib.gis.geos import Point
places = Property.objects.filter(lat__isnull=False, lng__isnull=False)
for place in places:
point = Point(place.lng, place.lat, srid=4326) # setting srid just to be safe
closest_city = City.objects.distance(point).order_by('distance')[0]
这会导致以下错误:
DatabaseError: geometry_distance_spheroid: Operation on two GEOMETRIES with different SRIDs
假设 SRID 没有默认为 4326,我在上面的代码中包含 srid=4326
并验证所有城市都有 City.center
的 SRID 为 4326:
In [6]: [c['center'].srid for c in City.objects.all().values('center')]
Out[6]: [4326, 4326, 4326, ...]
对于可能导致此问题的原因有什么想法吗?
更新:
SQL 查询的创建方式似乎存在一些问题。抛出错误后,查看 sql 显示:
In [9]: from django.db import connection
In [10]: print connection.queries[-1]['sql']
SELECT (ST_distance_sphere("model_city"."center",
ST_GeomFromEWKB(E'\\001\\001...\\267C@'::bytea))) AS "distance",
"model_city"."id", "model_city"."name", "listing_city"."center"
FROM "model_city" ORDER BY "model_city"."name" ASC LIMIT 21
看起来 django 正在将 distance()
的 point
参数转换为扩展众所周知的二进制文件。 如果我随后将 ST_GeomFromEWKB
更改为 ST_GeomFromText
一切正常。示例:
# SELECT (ST_distance_sphere("listing_city"."center",
ST_GeomFromText('POINT(-118 38)',4326))) AS "distance",
"model_city"."name", "model_city"."center" FROM "model_city"
ORDER BY "listing_city"."name" ASC LIMIT 5;
distance | name | center
------------------+-------------+----------------------------------------------------
3124059.73265751 | Akron | 0101000020E6100000795DBF60376154C01CB62DCA6C8A4440
3742978.5514446 | Albany | 0101000020E6100000130CE71A667052C038876BB587534540
1063596.35270877 | Albuquerque | 0101000020E6100000CC0D863AACA95AC036E7E099D08A4140
我在文档中找不到任何说明 如何使用的内容GeoQuerySet.distance()
转换为 SQL。我当然可以在查询中使用原始 SQL 来让事情正常工作,但更愿意将所有内容都很好地保留在 Django 框架中。
Given the following (simplified) models:
from django.contrib.gis.db import models
class City(models.Model):
center = models.PointField(spatial_index=True, null=True)
objects = models.GeoManager()
class Place(models.Model):
city = models.ForeignKey(City, null=True)
lat = models.FloatField(null=True)
lng = models.FloatField(null=True)
objects = models.GeoManager()
Forgetting for the moment that the lat/lng in Place should be moved to a PointField()
, I am trying to look through all of the Places
and find the closest city. Currently, I am doing:
from django.contrib.gis.geos import Point
places = Property.objects.filter(lat__isnull=False, lng__isnull=False)
for place in places:
point = Point(place.lng, place.lat, srid=4326) # setting srid just to be safe
closest_city = City.objects.distance(point).order_by('distance')[0]
This results in the following error:
DatabaseError: geometry_distance_spheroid: Operation on two GEOMETRIES with different SRIDs
Assuming that the SRIDs were not defaulting to 4326, I included srid=4326
in the above code and verified that all of the cities have City.center
has an SRID of 4326:
In [6]: [c['center'].srid for c in City.objects.all().values('center')]
Out[6]: [4326, 4326, 4326, ...]
Any ideas on what could be causing this?
UPDATE:
There seems to be something in how the sql query is created that causes a problem. After the error is thrown, looking at the sql shows:
In [9]: from django.db import connection
In [10]: print connection.queries[-1]['sql']
SELECT (ST_distance_sphere("model_city"."center",
ST_GeomFromEWKB(E'\\001\\001...\\267C@'::bytea))) AS "distance",
"model_city"."id", "model_city"."name", "listing_city"."center"
FROM "model_city" ORDER BY "model_city"."name" ASC LIMIT 21
It looks like django is turning the point
argument of distance()
into Extended Well-Known Binary. If I then change ST_GeomFromEWKB
to ST_GeomFromText
everything works fine. Example:
# SELECT (ST_distance_sphere("listing_city"."center",
ST_GeomFromText('POINT(-118 38)',4326))) AS "distance",
"model_city"."name", "model_city"."center" FROM "model_city"
ORDER BY "listing_city"."name" ASC LIMIT 5;
distance | name | center
------------------+-------------+----------------------------------------------------
3124059.73265751 | Akron | 0101000020E6100000795DBF60376154C01CB62DCA6C8A4440
3742978.5514446 | Albany | 0101000020E6100000130CE71A667052C038876BB587534540
1063596.35270877 | Albuquerque | 0101000020E6100000CC0D863AACA95AC036E7E099D08A4140
I can't find anything in the documentation that speaks to how GeoQuerySet.distance()
translates into SQL. I can certainly use raw SQL in the query to get things to work, but would prefer to keep everything nicely in the Django framework.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我认为这个错误:“对具有不同 SRID 的两个几何图形进行操作”
数据库上的“geometry_columns”表在要处理的表名之间设置了不同的 srid
***** 您应该自己更改它
i think this error : "Operation on two GEOMETRIES with different SRIDs"
"geometry_columns" table on your database is set different srid between your table name to process
***** you should change it yourself