如何在单个循环中逐一校验API返回字典的多个key,缺失时自动赋值为None
解决方案
核心思路是封装通用嵌套结构安全取值函数,一次性覆盖所有字典缺key、列表超界、中间值为空的异常场景,无需为每个字段单独写判断分支或异常捕获,各字段取值逻辑完全独立互不干扰。
步骤1:定义安全取值工具函数
def safe_get(root, *path, default=None): """ 从嵌套字典/列表结构中安全取值,取值失败自动返回默认值 :param root: 取值根对象 :param path: 取值路径,支持字符串(字典key)、整数(列表索引)混合传入 :param default: 取值失败返回的默认值,默认为None """ current = root for item in path: try: current = current[item] except (KeyError, IndexError, TypeError): # 分别覆盖字典无对应key、列表索引超界、当前值为非可索引类型的异常 return default return current
步骤2:重构业务代码
使用safe_get函数重构所有字段取值逻辑,每个字段仅需一行即可实现缺失自动设为None,同时增加接口返回兜底处理避免结构异常报错:
import requests import collections from django.conf import settings # 此处导入你自己的BookFilterForm、render等依赖 def safe_get(root, *path, default=None): current = root for item in path: try: current = current[item] except (KeyError, IndexError, TypeError): return default return current def your_view_func(request): book_import = [] if request.method == 'POST': filter_ch = BookFilterForm(request.POST) if filter_ch.is_valid(): cd = filter_ch.cleaned_data filter_choice = cd['choose_v'] filter_search = cd['search'] search_url = "https://www.googleapis.com/books/v1/volumes?" params = { 'q': f"{filter_choice}{filter_search}", 'key': settings.BOOK_DATA_API_KEY, 'maxResults': 2, 'printType': 'books' } r = requests.get(search_url, params=params) # 接口返回兜底,无items字段时返回空列表 results = safe_get(r.json(), 'items', default=[]) for result in results: volume_info = safe_get(result, 'volumeInfo', default={}) # ISBN取值直接通过路径取,缺对应索引自动返回None isbn_one = safe_get(volume_info, 'industryIdentifiers', 0, 'identifier') isbn_two = safe_get(volume_info, 'industryIdentifiers', 1, 'identifier') book_data = { 'title': safe_get(volume_info, 'title'), 'authors': safe_get(volume_info, 'authors', 0), 'publish_date': safe_get(volume_info, 'publishedDate'), 'isbn_one': isbn_one, 'isbn_two': isbn_two, 'page_count': safe_get(volume_info, 'pageCount'), 'thumbnail': safe_get(volume_info, 'imageLinks', 'thumbnail'), 'country': safe_get(result, 'saleInfo', 'country') } book_import.append(book_data) else: filter_ch = BookFilterForm() return render(request, "BookApp/book_import.html", {'book_import': book_import, 'filter_ch': filter_ch})
可选:ISBN特殊处理
如果你需要按ISBN类型(ISBN_10/ISBN_13)取值而非按索引取,可以在循环内补充以下逻辑:
# 构造ISBN类型到值的映射 isbn_map = {} industry_ids = safe_get(volume_info, 'industryIdentifiers', default=[]) for item in industry_ids: id_type = safe_get(item, 'type') id_val = safe_get(item, 'identifier') if id_type and id_val: isbn_map[id_type] = id_val # 按类型取ISBN,不存在则为None isbn_10 = isbn_map.get('ISBN_10') isbn_13 = isbn_map.get('ISBN_13')
内容的提问来源于stack exchange,提问作者Hide856
相关产品推荐
相关产品推荐

