在Django中使用哪个模型字段存储经度和纬度值?


74

目前,我想使用经度和纬度来存储我的用户位置,但这是来自Google地图,但是我将使用GeoDango和一些点来计算点之间的距离。

但是,我的第一个困惑是应该使用Django中的哪个字段存储经度和纬度值?我收到的信息有冲突。

官方文档使用FloatField https://docs.djangoproject.com/en/dev/ref/contrib/gis/tutorial/#geographic-models

lon = models.FloatField()
lat = models.FloatField()

几乎所有关于stackoverflow的答案都显示 DecimalField

long = models.DecimalField(max_digits=8, decimal_places=3)
lat = models.DecimalField(max_digits=8, decimal_places=3)

那我应该用什么呢?


我将使用FloatField。
布兰登

6
如果您有空间后端,则可以将这些位置存储在PointField中,这将使空间查询更加容易。docs.djangoproject.com/en/1.8/ref/contrib/gis/model-api/...
yellowcap

Answers:


101

浮点数通常是一个近似值,有关一些简单示例,请参见此处。将模型修改为可以得到非常好的结果DecimalField(max_digits=9, decimal_places=6),因为小数在坐标中非常重要,但是使用6以上基本上是没有意义的。


这个。并只需使用足够的小数位即可获得所需的精度。当您需要支持大范围的数量级时,浮点数很好。当将多个值组合在一起时,有时会用令人惊讶的舍入等行为来支付费用。
Christian Hudon

16
有关最大长度的坐标,请参见此处。我建议,DecimalField(max_digits=9, decimal_places=6)因为“坐标小数度的每个.000001差异的长度约为10厘米”。而且我怀疑您会使用的精度是否更高;)
grokpot

29

使用PointField存储纬度

p = Point(85.3240, 27.7172,srid=4326)

Django:1.X:

https://docs.djangoproject.com/zh-CN/1.11/ref/contrib/gis/model-api/#pointfield

Django:2.X:

https://docs.djangoproject.com/zh-CN/2.2/ref/contrib/gis/model-api/#pointfield

Django:3.X:https://docs.djangoproject.com/en/3.0/ref/contrib/gis/model-api/#pointfield


2
在您的settings.DATABASE引擎数据库配置中设置django.contrib.gis.db.backends.mysql
Amulya Acharya

2
正是我想要的。但是,该链接不包含有关如何使用字段或其中使用的参数的任何信息!我是django的新手,所以请让我知道在哪里可以找到更多信息
pravin

1
docs.djangoproject.com/en/2.0/ref/contrib/gis/model-api/…用于更高版本的django。使用默认的django.contrib.gis模型字段可以方便地提供序列化数据(例如Geojson序列化器)和Django形式的Inputs。
Amulya Acharya

3
请注意,您必须在系统上安装其他GDAL库,否则将收到此错误:django.core.exceptions.ImproperlyConfigured: Could not find the GDAL library
巴本·瓦尔丹扬

1
PointField很不错,但是需要安装postgis扩展。如果不需要处理许多与GIS相关的数据,则无需这样做。
dphans,2010年

3

DecimalField(max_digits=9, decimal_places=6)尝试从Google地图保存位置时,这里使用的建议对我造成了错误。

如果我们假设最常见的用例是从Maps API检索点位置,并在右键单击并选择“这里是什么?”时从Google Maps检索一个典型URL。产生类似:

https://www.google.com/maps/place/37°48'52.3"N+122°17'09.1"W/@37.814532,-122.2880467,17z

(随机的地方)

因此,经度在小数点前和后都有15位,这就是为什么接受的答案不起作用的原因。由于没有理由验证“尽可能短”并且数据库存储很便宜,因此我在使用:

    max_digits=22,
    decimal_places=16)

4
谢谢,但是我得到了(-36.82931199999999,174.71627980000001),所以我使用DecimalField(max_digits=22, decimal_places=16, blank=True, null=True)
CK

啊! 感谢您的报告-我将更新答案。
shacker,
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.