在 Django 中使用 GeoPy 和 ImportExport 进行地理编码

Geocoding with GeoPy and ImportExport in Django

我正在通过 ImportExport plugin, and at the point of saving this the model runs a geocoding process with GeoPy.

将地址的 .CSV 文件中的数据集导入到 Django 中的模型中

90% 的时间都有效,但有一些条目出现以下错误:

... in save _, latlon = geocoder.geocode(address) TypeError: cannot unpack non-iterable NoneType object

我猜地理编码没有找到地址,但我不确定为什么它不只是将该字段留空。我在 Django 文档、GeoPy 文档和 google 地图地理编码文档中查找了相关部分,但似乎没有找到任何关于如何修复它的提示。

下面是更完整的回溯错误输出:

Traceback (most recent call last):

File "C:\Users\henry\webvenv\aavenv\lib\site-packages\import_export\resources.py", line 522, in import_row

self.save_instance(instance, using_transactions, dry_run)

File "C:\Users\henry\webvenv\aavenv\lib\site-packages\import_export\resources.py", line 315, in save_instance

instance.save()

File "C:\Users\henry\webvenv\project\architects\models.py", line 51, in save

_, latlon = geocoder.geocode(address)

TypeError: cannot unpack non-iterable NoneType object

下面是 app/model.py,它由 .CSV 文件和 运行 地理编码过程填充:

from django.conf import settings

from urllib.request import URLError

from django.contrib.gis.db import models

from django.contrib.gis import geos

import geopy.geocoders
from geopy.geocoders import GoogleV3


class Architect(models.Model):

    id = models.CharField(max_length=100, primary_key=True)
    sname = models.CharField(max_length=100)
    fname = models.CharField(max_length=100)
    a1 = models.CharField(max_length=100)
    a2 = models.CharField(max_length=100)
    a3 = models.CharField(max_length=100)
    a4 = models.CharField(max_length=100)
    a5 = models.CharField(max_length=100)
    a6 = models.CharField(max_length=100)
    pcode = models.CharField(max_length=100)
    author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, null=True)
    location = models.PointField(u"longitude/latitude", blank=True, null=True)

    objects = models.Manager()

#Original def:
#    def __str__(self):
#        return self.id

    def __unicode__(self):
        return self.id

    def save(self, **kwargs):
        if not self.location:
            address = u'%s %s %s %s %s %s' % (self.a2, self.a3, self.a4, self.a5, self.a6, self.pcode)
            address = address.encode('utf-8')
            geocoder = GoogleV3(api_key='my API key')
            try:
                _, latlon = geocoder.geocode(address)
            except (URLError, ValueError):
                
                pass
            else:
                point = "POINT(%s %s)" % (latlon[1], latlon[0])
                self.location = geos.fromstr(point)
        super(Architect, self).save()
    

我现在似乎已经解决了我的问题

我的解决方案涉及将 'TypeError' 添加到异常中。

我还添加了 10 秒的超时来帮助解决出现会话超时错误的地理编码,据我所知,GeoPy 的默认超时是 1 秒。

如果有更简洁或更有效的方式来编写此代码,我将不胜感激。

...
    def save(self, **kwargs):
        if not self.location:
            address = u'%s %s %s %s %s %s' % (self.a2, self.a3, self.a4, self.a5, self.a6, self.pcode)
            address = address.encode('utf-8')
            geocoder = GoogleV3(api_key='My API Key')
            try:
                _, latlon = geocoder.geocode(address, timeout=10)
            except (URLError, ValueError, TypeError):

                pass
            else:
                point = "POINT(%s %s)" % (latlon[1], latlon[0])
                self.location = geos.fromstr(point)
        super(Architect, self).save()