【问题标题】:Does not raise exception on "Unknown SRID"不会在“未知 SRID”上引发异常
【发布时间】:2016-05-03 13:29:27
【问题描述】:

拿这个模型:

from django.contrib.gis.db import models


class Location(models.Model):
    point = models.PointField(null=True, blank=True)

然后尝试执行这个,故意给它一个错误的SRID:

from django.contrib.gis.geos import Point
from testpoint.models import Location

some_location = Location()
some_location.point = Point(x=15, y=16, srid=210)
some_location.save()

在执行最后一条语句some_location.save() 时,控制台上会显示消息“unknown SRID: 210”。到现在为止还挺好。问题是.save()返回成功,point中存的是null;但我想要的是什么都没有被保存并引发异常。

Django 似乎将此 SQL 发送给了 spatialite:

INSERT INTO "testpoint_location" ("point")
VALUES (Transform(GeomFromText('POINT(15.0 16.0)', 210), 4326))

spatialite 似乎执行了它(在控制台上打印了警告),而没有告诉 Django 出了什么问题。

当 SRID 错误时,如何告诉 spatialite 失败并返回错误?

【问题讨论】:

    标签: python django geodjango spatialite


    【解决方案1】:

    在 GeoDjango Database API documentation 上声明:

    此外,如果 GEOSGeometry 位于与字段不同的坐标系中(具有不同的 SRID 值),则将使用空间数据库的转换过程将其隐式转换为模型字段的 SRID。

    BaseSpatialFieldPointField 的基础)上,默认 srid 设置为 4326。它会警告您 srid=210 不存在并继续将 (x,y) 对转换为EPSG:4326。

    我看到了两种解决方法(至少目前):

    1. 简单的方法:通过在模型定义中定义所有东西来强制转换为 EPSG:2100(希腊网格):

      class Location(models.Model):
          point = models.PointField(null=True, blank=True, srid=2100)
      
    2. (稍微)更复杂的方法:创建自定义异常和接受的 SRID 列表:SRIDS=[2100, 4326, 3857,...],对照该列表检查传入的 srid,如果不匹配,请提高自定义异常:

      my_app/exceptions.py:

      class UnknownSRID(Exception):
          def __init__(self, message=None):
              self.message = message
      

      my_app/my_test.py:

      from django.conf import settings
      from django.contrib.gis.geos import Point
      
      from testpoint.exceptions import UnknownSRID
      from testpoint.models import Location
      
      some_location = Location()
      test_srid=210
      if test_srid not in settings.SRIDS:
          raise UnknownSRID(
              'SRID {} not in list of acceptable SRIDs'.format(test_srid)
          )
      
      some_location.point = Point(x=15, y=16, srid=test_srid)
      some_location.save()
      

    【讨论】:

    • 谢谢。不,实际上我并不是在寻找解决方法。我想看看是否存在真正的解决方案(即让 sqlite 行为正常)。让我看看我最后做了什么……是的,我实际上在使用 PostgreSQL,我只在开发中需要它,这样单元测试才能真正运行;所以我所做的是跳过 SQLite 的测试。 github.com/openmeteo/enhydris/blob/…
    • @AntonisChristofides 好吧,这是解决这个问题的一种方法。如果您希望能够使用此测试,您可以使用第二种解决方案并在测试中添加:assertRaises(UnknownSRID,...)
    猜你喜欢
    • 2014-03-02
    • 2021-08-09
    • 1970-01-01
    • 1970-01-01
    • 2019-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多