如何使用GeoDjango转换几何体列

时间:2014-03-27 16:36:09

标签: django geospatial django-queryset geodjango

我正在尝试在django中转换几何列,这是我的模型

class Network(models.Model):
    name = models.CharField(max_length=50, blank=True)
    alias = models.CharField(max_length=100, blank=True)
    geometry = models.GeometryField(srid=3857, null=True, blank=True)
    bbox = models.GeometryField(srid=3857, null=True, blank=True)
    objects = models.GeoManager()

    class Meta:
        db_table = u'tbl_network'

    def __unicode__(self):
        return '%s' % self.name

我正在尝试转换 bbox 列,但GeoQuerySet会自动转换几何

Network.objects.transform(srid=3857).values('geometry','bbox')

以上django查询的SQL查询输出

  SELECT ST_Transform("tbl_network"."geometry", 3857), "tbl_network"."bbox" FROM "tbl_network"

所以我尝试了不同的方法,现在排除 geometry

 Network.objects.transform(srid=3857).values('bbox')

以上django查询的SQL查询输出

 SELECT "tbl_network"."bbox" FROM "tbl_network"

现在GeoQuerySet完全忽略了转换函数。

所以我的问题是:如何转换特定的模型列?

我收到了这个django论坛的回复,但我无法理解多个几何列的问题

  

"我看到第一个查询有效,第二个查询无效   转变。我认为这个问题可能与你有2个问题有关   同一Postgis表中的几何列。

     

它们都列在Postgis的geometry_columns视图中。   通常只有1可以是默认值。在这种情况下几何,所以   Geodjango / Postgis认为它是一个空间专栏。但是当它   得到bbox它没有认识到它并且不知道FROM是什么   (当前)srid是如此的变形不会起作用。

     

一种选择是返回数据,然后转换一次   将空间对象放入python变量中。 "

任何人都可以解释这个回复吗?

1 个答案:

答案 0 :(得分:3)

在您的模型中,您有两个几何字段:geometrybbox。几何字段的大多数方法(例如变换)都使用其中一个字段作为默认值。调用该方法只会影响该特定字段,第二个几何字段将保持不变。

要变换两个几何,您必须调用两次变换方法,每个字段调用一次。您可以使用django docs here

中所述的field_name参数指定字段

使用您的模型,您可以执行以下操作:

# Get network models
queryset = Network.objects.all()

# Transform geometry field
queryset = queryset.transform(3857, field_name='geometry')

# Transform bbox field
queryset = queryset.transform(3857, field_name='bbox')

此外,通过阅读您的示例,我想知道您使用的bbox字段是否代表geometry字段的边界框。如果是这种情况,则表示您正在存储冗余信息,您可以删除bbox字段。只需使用GEOSGEometry extent property获取几何体的边界框,然后您也只需要变换主几何体:

# Network model with only one geometry field
class Network(models.Model):
    name = models.CharField(max_length=50, blank=True)
    alias = models.CharField(max_length=100, blank=True)
    geometry = models.GeometryField(srid=3857, null=True, blank=True)
    objects = models.GeoManager()

然后

# Transform geometry field (which is the default if there is only one geom field)
queryset = Network.objects.all().tansform(3857)

# Bbox coordinates of first geometry in new coordinates
ntwork = queryset[0]
bbox = ntwork.geometry.extent