Migration Guide

Migrating from 2.2 to 2.3

A breaking API change was accidentally introduced into the 2.3 minor release by renaming some nested fields of BaseCollaborators and WorkspaceCollaborators.

    • base.collaborators().invite_links.base_invite_links
      has become base.collaborators().invite_links.via_base
    • base.collaborators().invite_links.workspace_invite_links
      has become base.collaborators().invite_links.via_workspace
    • ws.collaborators().invite_links.base_invite_links
      has become ws.collaborators().invite_links.via_base
    • ws.collaborators().invite_links.workspace_invite_links
      has become ws.collaborators().invite_links.via_workspace
    • ws.collaborators().individual_collaborators.base_collaborators
      has become ws.collaborators().individual_collaborators.via_base
    • ws.collaborators().individual_collaborators.workspace_collaborators
      has become ws.collaborators().individual_collaborators.via_workspace
    • ws.collaborators().group_collaborators.base_collaborators
      has become ws.collaborators().group_collaborators.via_base
    • ws.collaborators().group_collaborators.workspace_collaborators
      has become ws.collaborators().group_collaborators.via_workspace

Migrating from 1.x to 2.0

With the 2.0 release, we’ve made some breaking changes to the pyAirtable API. These are summarized below. You can read more about the rationale behind these changes in #257, and you see a list of changes and new features in the Changelog.

ApiAbstract removed

We’ve removed the pyairtable.api.abstract module. If you had code which inherited from ApiAbstract, you will need to refactor it. We recommend taking an instance of Api as a constructor parameter, and using that to construct Table instances as needed.

Changes to Api, Base, and Table

Api, Base, and Table no longer inherit from the same base class. Each has its own scope of responsibility and has methods which refer to the other classes as needed. See Getting Started.

For a period of time, the constructor for Base and Table will remain backwards-compatible with the previous approach (passing in str values), but doing so will produce deprecation warnings.

See below for supported and unsupported patterns:

# The following are supported:
>>> api = Api(api_key, timeout=..., retry_strategy=..., endpoint_url=...)
>>> base = api.base(base_id)  # [str]
>>> base = Base(api, base_id)  # [Api, str]
>>> table = base.table(table_name)  # [str]
>>> table = api.table(base_id, table_name)  # [str, str]
>>> table = Table(None, base, table_name)  # [None, Base, str]

# The following are still supported but will issue a DeprecationWarning:
>>> base = Base(api_key, base_id)  # [str, str]
>>> table = Table(api_key, base_id, table_name)  # [str, str, str]

# The following will raise a TypeError for mixing str & instances:
>>> table = Table(api_key, base, table_name)  # [str, Base, str]
>>> table = Table(api, base_id, table_name)  # [Api, str, str]

# The following will raise a TypeError. We do this proactively
# to avoid situations where self.api and self.base don't align.
>>> table = Table(api, base, table_name)  # [Api, Base, str]

You may need to change how your code looks up some pieces of connection metadata; for example:

Method/attribute in 1.5

Method/attribute in 2.0

base.base_id

base.id

table.table_name

table.name

table.get_base()

table.base

table.base_id

table.base.id

table.table_url

table.url

table.get_record_url()

table.record_url()

There is no fully exhaustive list of changes; please refer to the API documentation for a list of available methods and attributes.

Retry by default

  • By default, the library will retry requests up to five times if it receives a 429 status code from Airtable, indicating the base has exceeded its QPS limit.

Changes to the ORM

  • Model.all and Model.first return instances of the model class instead of returning dicts.

  • LinkField now defaults to lazy=False. The first time your code accesses the field, it will perform one or more API calls to retrieve field data for linked records. You can disable this by passing lazy=True when creating the field.

Changes to types

  • All functions and methods in this library have full type annotations that will pass mypy --strict. See the pyairtable.api.types module for more information on the types this library accepts and returns.

batch_upsert has a different return type

  • batch_upsert() now returns the full payload from the Airtable API, as opposed to just the list of records (with no indication of which were created or updated). See UpsertResultDict for more details.

Found a problem?

While these breaking changes were intentional, it is very possible that the 2.0 release has bugs. Please take a moment to read our contribution guidelines before submitting an issue.


Migrating from 0.x to 1.0

Airtable Python Wrapper was renamed to pyAirtable starting on its first major release, 1.0.0. The docs for the older release will remain on Read the Docs, the source code on this branch. The last 0.x release will remain available on PyPI.

You can read about the reasons behind the renaming here.

New Features in 1.0

  • Type Annotations

  • Simpler API

  • Formulas

  • ORM Models

API Changes in 1.0

We used this new major release to make a few breaking changes:

  • Introduced a simpler API that’s more closely aligned with Airtable API’s patterns.

  • Created more a flexible API (Api, Base, Table)

Changes

0.x (airtable-python-wrapper)

1.0 (pyAirtable)

Airtable()

Api, Base, Table

get()

get()

get_iter()

iterate()

get_all()

all()

search()

all(formula=match({"Name" : "X"})

match(**kwargs)

first(formula=match({"Name" : "X"})

insert()

create()

update()

update()

replace()

use update(replace=True)

delete()

delete()