25
loading...
This website collects cookies to deliver better user experience
airtable.py
with example functions you'll build here. There is also a Jupyer notebook, AirtablePractice.ipynb
in the repo you can use to follow along..env
file to keep it secret..env
file naming it AIRTABLE_TOKEN
. Make sure you keep this token private and do not share it with anyone! If you're committing files to a GitHub repo (or any other source control system), make sure you exclude the .env
to avoid accidentally exposing this information!.env
file naming it AIRTABLE_BASE_ID
.airtable.py
. Include the following at the top of the file:import os
from python_dotenv import load_dotenv
load_dotenv()
AIRTABLE_TOKEN = os.getenv("AIRTABLE_TOKEN")
AIRTABLE_BASE_ID = os.getenv("AIRTABLE_BASE_ID")
python_dotenv
library, the variables you included in your .env
are read into two variables, AIRTABLE_TOKEN
and AIRTABLE_BASE_ID
, allowing you to utilize them in the rest of your script.api.airtable.com/v0
api.airtable.com/v0
, will remain constant across all requests. The Base ID will depend on the specific Airtable Base you are using. Since this tutorial will use the same base, we can create another variable, AIRTABLE_URL
, at the top of the file that you can use to construct the endpoint for each request. The code at the top of airtable.py
should now look like this:import os
from python_dotenv import load_dotenv
load_dotenv()
AIRTABLE_TOKEN = os.getenv("AIRTABLE_TOKEN")
AIRTABLE_BASE_ID = os.getenv("AIRTABLE_BASE_ID")
AIRTABLE_URL = f"https://api.airtable.com/v0/{AIRTABLE_BASE_ID}"
golf-scorecard
containing four columns: the date, hole number, par, and the number of strokes for the hole.records
, defining an array of the records that will be added to the sheet. Each record in the array is a dictionary with a key fields
, containing a dictionary that maps values to the columns in the sheet. Here's an example data payload for adding scores to the Airtable for the first two holes.new_data = {
"records": [
{
"fields": {
"Date": "2021-09-22",
"Hole": 1,
"Par": 4,
"Score": 5
}
},
{
"fields": {
"Date": "2021-09-22",
"Hole": 2,
"Par": 4,
"Score": 4
}
}
]
}
airtable.py
called add_new_scores
that will take the new_data
scores as input and add them to the Airtable.def add_new_scores(scores):
"""Add scores to the Airtable."""
url = f"{AIRTABLE_URL}/golf-scores"
headers = {
'Authorization': f'Bearer {AIRTABLE_TOKEN}',
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=json.dumps(scores))
return response
AIRTABLE_URL
variable we created earlier. The only addition is the name of our sheet, golf-scores
, which has been added to the URL to instruct Airtable that we want to add records to the golf-scores
sheet of our base. If you want to add scores to a different sheet, you can substitute the sheet's name in the URL.AIRTABLE_TOKEN
so that Airtable can confirm the request is authorized.request
module, passing the scores payload along with the request.def chunk(arr, n):
for i in range(0, len(arr), n):
yield arr[i:i + n]
for c in chunk(data["records"], 10):
chunk_data = {
"records": c
}
response = airtable.add_new_scores(chunk_data)
chunk
function returns a generator that will break down the records into groups of size n
where n
should not be greater than 10. Next, you can iterate over the n
sized chunks from your data and call the add_new_scores
function during each iteration to add the records to Airtable.airtable.py
file to read records from the golf-scores
sheet.def get_golf_scores():
"""Add scores to the Airtable."""
url = f"{AIRTABLE_URL}/golf-scores"
headers = {
'Authorization': f'Bearer {AIRTABLE_TOKEN}',
'Content-Type': 'application/json'
}
response = requests.request("GET", url, headers=headers)
return response
golf-scores
sheet and include your authentication header information. The two differences are that you will submit a GET request instead of a POST request, and you do not need to pass a data payload along with the request.id
uniquely identifying the record, a field dictionary with the values for the record, and a createdTime
key. An example response is below.{
"records":
[
{
"id": "<AIRTABLE_RECORD_ID>",
"fields": {
"Date": 2021-09-22,
"Hole": 1,
"Par": 4,
"Score": 5
},
"createdTime": <some_time>
}
...
]
}
get_scores_for_hole
, to your file. In this function, you will query the golf-scores
sheet in Airtable and return only the records for the hole number you send to the function. Instead of returning all table fields, your response will only contain the Hole
and score
fields for each record. Enter the following function in your file.def get_scores_for_hole(hole):
"""Get scores for a specific hole."""
url = f"{AIRTABLE_URL}/golf-scores"
headers = {
'Authorization': f'Bearer {AIRTABLE_TOKEN}',
'Content-Type': 'application/json'
}
params = {
"fields": ["Hole", "Score"],
"filterByFormula": f"Hole={hole}"
}
response = requests.request("GET", url, headers=headers, params=params)
return response
params
object in your API request. The fields
key instructs Airtable what fields to return in the response, and filterByFormula
specifies the filter to apply to the sheet.offset
value in its response. To retrieve more than 100 records, you will need to issue a new request that includes the value of offset
. The function get_scores_by_page
below accepts a parameter offset
to instruct Airtable to retrieve the next page of results.def get_golf_scores_by_page(offset=None):
"""Retrieve records from Airtable and apply offset is necessary."""
url = f"{AIRTABLE_URL}/golf-scores"
headers = {
'Authorization': f'Bearer {AIRTABLE_TOKEN}',
'Content-Type': 'application/json'
}
params = {
"pageSize": 100
}
if offset:
params["offset"] = offset
response = requests.request("GET", url, headers=headers, params=params)
return response
offset
value, you will iteratively retrieve more records. When all records are retrieved, Airtable will stop sending offset
in the response. An example implementation is below.results = airtable.get_golf_scores_by_page()
while "offset" in results.json():
results = airtable.get_golf_scores_by_page(response.json()["offset"])
updated_records = {
"records": [
{
"id": <record_id>,
"fields": {
"Score": 4
},
}
]
}
update_record_fields
in your Python file:def update_record_fields(updated_records):
"""Update specific field values for a record."""
url = f"{AIRTABLE_URL}/golf-scores"
headers = {
'Authorization': f'Bearer {AIRTABLE_TOKEN}',
'Content-Type': 'application/json'
}
response = requests.request("PATCH", url, headers=headers, data=json.dumps(updated_records))
return response
updated_records
, defining the records and values to be updated. Replace <record_id>
in the updated_records
object with an ID from your table, then use it as input to update_record_fields
. If you look at the record in Airtable, the value for the Hole_Number
field should have changed, and all other values should remain the same.replace_record_fields
:def replace_record_fields(updated_records):
"""Updates the records."""
url = f"{AIRTABLE_URL}/golf-scores"
headers = {
'Authorization': f'Bearer {AIRTABLE_TOKEN}',
'Content-Type': 'application/json'
}
response = requests.request("PUT", url, headers=headers, data=json.dumps(updated_records))
return response
update_record_fields
. The only difference is that we are using a PUT request instead of a PATCH here. This time let's try to change the score of the first hole to 6. Use the following payload as input to replace_record_fields
, use the same record ID as the previous request and let's see what happens.updated_records = {
"records": [
{
"id": <record_id>,
"fields": {
"Score": 6
},
}
]
}
delete_records
to your file.def delete_records(records):
"""Delete the records."""
url = f"{AIRTABLE_URL}/golf-scores"
headers = {
'Authorization': f'Bearer {AIRTABLE_TOKEN}',
'Content-Type': 'application/json'
}
params = {
"records[]": records
}
response = requests.request("DELETE", url, headers=headers, params=params)
return response