You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将API返回的空字符串转为0存入Django数据库?

解决API空字符串转整数默认值的问题

问题场景

从外部API拉取跑道数据并存入数据库时,遇到如下报错:

ValueError at /
Field 'he_displaced_threshold_ft' expected a number but got ''.

原因是API返回的JSON中,部分对应数据库IntegerField的字段为空字符串,无法直接存入数字类型字段。

相关代码

services.py

def get_runways():
    params = {
        "apiToken": "SECRET",
    }
    api_base = "https://airportdb.io/api/v1/airport/KMIA"
    api_result = requests.get(api_base, params)
    api_response = api_result.json()

    for the runway in api_response["runways"]:
        runway_data, created = Runway.objects.update_or_create(
            airport_ident=Airport.objects.get(ident=runway["airport_ident"]),
            length_ft=runway["length_ft"],
            width_ft=runway["width_ft"],
            surface=runway["surface"],
            lighted=runway["lighted"],
            closed=runway["closed"],
            le_ident=runway["le_ident"],
            le_latitude_deg=runway["le_latitude_deg"],
            le_longitude_deg=runway["le_longitude_deg"],
            le_elevation_ft=runway["le_elevation_ft"],
            le_heading_degT=runway["le_heading_degT"],
            le_displaced_threshold_ft=runway["le_displaced_threshold_ft"],
            he_ident=runway["he_ident"],
            he_latitude_deg=runway["he_latitude_deg"],
            he_longitude_deg=runway["he_longitude_deg"],
            he_elevation_ft=runway["he_elevation_ft"],
            he_heading_degT=runway["he_heading_degT"],
            he_displaced_threshold_ft=runway["he_displaced_threshold_ft"],
        )
        runway_data.save()

    return runway

models.py

class Runway(models.Model):
    airport_ident = models.ForeignKey(Airport, on_delete=models.CASCADE)
    length_ft = models.IntegerField(default=None, blank=True, null=True)
    width_ft = models.IntegerField(default=None, blank=True, null=True)
    surface = models.CharField(max_length=50, blank=True, null=True)
    lighted = models.IntegerField(default=None, blank=True, null=True)
    closed = models.PositiveBigIntegerField(default=None, blank=True, null=True)
    le_ident = models.CharField(max_length=5, blank=True, null=True)
    le_latitude_deg = models.FloatField(default=None, blank=True, null=True)
    le_longitude_deg = models.FloatField(default=None, blank=True, null=True)
    le_elevation_ft = models.IntegerField(default=None, blank=True, null=True)
    le_heading_degT = models.FloatField(default=None, blank=True, null=True)
    le_displaced_threshold_ft = models.IntegerField(blank=True, null=True)
    he_ident = models.CharField(max_length=5, blank=True, null=True)
    he_latitude_deg = models.FloatField(default=None, blank=True, null=True)
    he_longitude_deg = models.FloatField(default=None, blank=True, null=True)
    he_elevation_ft = models.IntegerField(default=None, blank=True, null=True)
    he_heading_degT = models.FloatField(default=0, blank=True, null=True)
    he_displaced_threshold_ft = models.IntegerField(default=0, blank=True, null=True)

    def __str__(self):
        return self.airport_ident.ident

解决方案

方法1:单个字段处理函数(推荐)

编写工具函数统一处理空字符串转默认值的逻辑,同时兼容非数字、None等异常情况:

def parse_to_int(value, default=0):
    if value == '':
        return default
    try:
        return int(value)
    except (ValueError, TypeError):
        return default

在update_or_create中调用该函数处理对应字段:

runway_data, created = Runway.objects.update_or_create(
    airport_ident=Airport.objects.get(ident=runway["airport_ident"]),
    length_ft=parse_to_int(runway["length_ft"]),
    width_ft=parse_to_int(runway["width_ft"]),
    surface=runway["surface"],
    lighted=parse_to_int(runway["lighted"]),
    closed=parse_to_int(runway["closed"]),
    le_ident=runway["le_ident"],
    le_latitude_deg=runway["le_latitude_deg"],
    le_longitude_deg=runway["le_longitude_deg"],
    le_elevation_ft=parse_to_int(runway["le_elevation_ft"]),
    le_heading_degT=runway["le_heading_degT"],
    le_displaced_threshold_ft=parse_to_int(runway["le_displaced_threshold_ft"]),
    he_ident=runway["he_ident"],
    he_latitude_deg=runway["he_latitude_deg"],
    he_longitude_deg=runway["he_longitude_deg"],
    he_elevation_ft=parse_to_int(runway["he_elevation_ft"]),
    he_heading_degT=runway["he_heading_degT"],
    he_displaced_threshold_ft=parse_to_int(runway["he_displaced_threshold_ft"]),
)

方法2:批量处理所有整数字段

如果需要处理的字段较多,可批量遍历字典转换,减少重复代码:

def get_runways():
    params = {
        "apiToken": "SECRET",
    }
    api_base = "https://airportdb.io/api/v1/airport/KMIA"
    api_result = requests.get(api_base, params)
    api_response = api_result.json()

    # 定义需要转换为整数的字段列表
    int_field_names = [
        'length_ft', 'width_ft', 'lighted', 'closed', 'le_elevation_ft',
        'le_displaced_threshold_ft', 'he_elevation_ft', 'he_displaced_threshold_ft'
    ]

    for runway in api_response["runways"]:
        # 批量处理空字符串转0
        for field in int_field_names:
            value = runway.get(field)
            if value == '':
                runway[field] = 0
            elif value is not None:
                try:
                    runway[field] = int(value)
                except ValueError:
                    runway[field] = 0

        runway_data, created = Runway.objects.update_or_create(
            airport_ident=Airport.objects.get(ident=runway["airport_ident"]),
            **runway  # 直接展开处理后的字典
        )
        runway_data.save()

    return runway

方法3:模型层处理(可选)

在模型的save方法中添加处理逻辑,但该方法仅在调用模型save时生效,update_or_create可能在验证阶段就报错,优先级低于前两种:

class Runway(models.Model):
    # ... 原有字段定义 ...

    def save(self, *args, **kwargs):
        # 处理需要转换的字段
        int_fields = [
            'length_ft', 'width_ft', 'lighted', 'closed', 'le_elevation_ft',
            'le_displaced_threshold_ft', 'he_elevation_ft', 'he_displaced_threshold_ft'
        ]
        for field in int_fields:
            value = getattr(self, field)
            if value == '':
                setattr(self, field, 0)
            elif value is not None:
                try:
                    setattr(self, field, int(value))
                except ValueError:
                    setattr(self, field, 0)
        super().save(*args, **kwargs)

内容的提问来源于stack exchange,提问作者ejcortinas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 19:06:26