Получение более 100 записей с Airtable
Я создаю приложение, которое получает базу данных на Airtable с библиотекой запросов и преобразует ее в список.
Моя проблема в том, что я могу получить только 100 записей с запросом URL. Я пытался найти решение в API Airtable, но изменения в URL для вставки maxRecords не работали.
Я использую этот URL для получения данных. Но он возвращает только 100 записей.
https://api.airtable.com/v0/appP6G7OJmLzUCoUt/Table%201?api_key=MY_KEY
Я читал о maxRecords и разбивке на страницы, но не смог найти способ изменить URL, чтобы использовать это.
Кто-нибудь может мне помочь?
1 ответ
TLDR:
Вы можете попробовать использовать рекурсивную функцию, которая выполняется, когда в ответе http (json) существует смещение.
Подтверждение:
Это решение заняло 7 часов исследований, поиска неисправностей и советов от великого и влиятельного Дуга. Проект использует Alamofire для выполнения http-запросов и SwiftyJson для доступа к JSON.
Причина:
В документации Airtable указывается, что их лимит скорости составляет 100 единиц на запрос. Если запрос содержит более 100 элементов, запрос будет включать смещение.
Они дают указание включить смещение в ваш следующий запрос, чтобы получить следующие 100 результатов. Но они не объясняют и не демонстрируют, как это сделать.
Решение:
Он был протестирован на получение 2565 элементов из 25 HTTP-запросов. Написанная на Swift, логика проста:
Напишите рекурсивную функцию с аргументом для необязательного смещения. Вызовите функцию без смещения. Проверьте HTTP-ответ (JSON) для смещения. Если смещение существует, сохраните http-запрос (json) в массиве вне функции. Затем вызовите эту же функцию изнутри себя - на этот раз со смещением.
Расширенный код здесь.
func requestAirtableRecords(forTable table: String, withTableView tableView: String, withOffset offset: String?, completion: @escaping ([JSON]) -> ()) {
let parameters: [String: Any] = offset != nil ? ["view": tableView, "offset": offset!] : ["view": tableView]
do {
let url: URLRequest = try self.requestRecordsURL(table: table, method: HttpRequest.get, parameters: parameters)!
Alamofire.request(url).responseJSON { (response) in
switch response.result {
case .success(_):
let json = JSON(response.result.value!)
self.jsonArray.append(json)
let nextOffset = json["offset"]
if nextOffset.exists() {
self.requestAirtableRecords(forTable: table, withTableView: tableView, withOffset: nextOffset.stringValue, completion: { _ in
completion(self.jsonArray)
})
} else {
completion(self.jsonArray)
}
case .failure(let error):
print(error)
}
}
} catch {
print("Error: Unable to request records from Airtable.")
}
}
Как я видел в других постах, многие люди имели дело с той же проблемой. Я пытался найти решения, но я не смог исправить это с помощью URL.
Хотя, слава богу, все данные из Airtable в Python легче получить с помощью библиотеки API Airtable. ( http://airtable-python-wrapper.readthedocs.io/en/master/)
Есть функция get_all(), которая принимает аргумент maxRecords. Просто вызовите x.get_all() без аргументов внутри, и API вернет каждую запись в таблице.
Это код, который я использовал в Python для решения этой проблемы - в соответствии с ответом Кристиана я использовал рекурсивный вызов. Однако я публикую этот код, потому что OP запросил ответ на Python.
def get_airtable_data(email_dict=None, offset=None):
"""
queries airtable and creates a dict of {name: email} from records that are
listed as subscribed
"""
if email_dict is None:
email_dict = {}
r = requests.get(request_url, headers={"Authorization": bearer_token}, params={"pageSize": 100, "offset": offset})
r_json = json.loads(r.text)
for item in r_json["records"]:
if item["fields"]["subscribed"] == 1:
email_dict[item["fields"]["Name"]] = item["fields"]["Primary Email"]
if r_json["offset"] is None:
print("all data loaded")
else:
try:
get_airtable_data(email_dict, r_json["offset"])
except KeyError:
print("all data loaded")
return email_dict