首页 > 解决方案 > 如何将以文本格式从 API 返回的数据插入 Django 模型

问题描述

我正在使用以文本格式返回数据的 API ( https://www.metoffice.gov.uk/pub/data/weather/uk/climate/datasets/Tmax/date/UK.txt )。因此,对于返回的数据,我想将这些数据添加到 Django 模型中。所以现在我遇到了一个问题,即我应该如何解析数据以便将它们添加到模型中。因为该 API 返回的数据如您所见,2021 年并没有所有数据。

目前,我在 Django 模型中有 18 个字段(每个字段对应每个值),我的方法是使用正则表达式提取具有数字常量模式的所有数据,并使用提取的数据,将数据插入到 DB 模型中遍历列表。但问题是 2021 年没有所有数据,我使用的正则表达式只是从 API 返回的字符串中提取数值。

例如:

ear    jan    feb    mar    apr    may    jun    jul    aug    sep    oct    nov    dec     win     spr     sum     aut     ann
2021    4.9    7.0    9.8   10.9   13.4   18.7   21.1   18.9   18.7   14.0                  6.21   11.35   19.56    

到目前为止我写的代码。

numeric_const_pattern = '[-+]? (?: (?: \d* \. \d+ ) | (?: \d+ \.? ) )(?: [Ee] [+-]? \d+ ) ?'
rx = re.compile(numeric_const_pattern, re.VERBOSE)

r = requests.get('https://www.metoffice.gov.uk/pub/data/weather/uk/climate/datasets/Tmax/date/UK.txt')

years_data = r.text.split('\n', 6)[6].split('\n')
for year in years_data:
    print(rx.findall(year))
    # here i want to insert the values to the django model.

那么我应该如何继续为此构建逻辑呢?任何帮助将不胜感激。

标签: pythondjango

解决方案


您可以编写一个字典,例如MAP_ROW_TO_FIELDS将每个字段映射到您在 x 轴上的位置。

然后遍历每一行并处理字典键中定义的值,忽略空或无效的位置。

接下来,setattr在每个键中使用,您可以将值直接设置为模型实例。

import re
import requests


# The key value are the same that the model field names.
# In the tuple the x position of each field (start, end).
MAP_ROW_TO_FIELDS = {
    'year': (0, 5),
    'jan': (6, 11),
    'feb': (12, 19),
    'mar': (20, 26)
    # add others here
}

RE_INT = re.compile('^\d+$') 
RE_FLOAT = re.compile('^\d+\.\d+$') 


url = "https://www.metoffice.gov.uk/pub/data/weather/uk/climate/datasets/Tmax/date/UK.txt"
response = requests.get(url)


line_num = 0
for line in response.text.split('\n'):
    line_num += 1
    if line_num > 6 and line.strip(): # avoid empty lines
        row = RowModel()
        
        for key in MAP_ROW_TO_FIELDS.keys():
            val = line[MAP_ROW_TO_FIELDS[key][0]: MAP_ROW_TO_FIELDS[key][1]]
            val = val.strip()
            # If data match, saves directly to the model.
            if RE_INT.match(val):
                setattr(row, key, int(val))
            elif RE_FLOAT.match(val):
               setattr(row, key, float(val))
            else:
                # print(line)
                print('Unknow value "%s" for field %s' % (val, key))
        
        # Save to database
        row.save()
      

可以轻松获取在代码编辑器中打开文本文件的 x 坐标。


推荐阅读