gtalarico / pyairtable

Python Api Client for Airtable
https://pyairtable.readthedocs.io
MIT License
786 stars 139 forks source link

ORM LinkField: many-to-many relation modeling #176

Closed larsakerson closed 1 year ago

larsakerson commented 2 years ago

I'm having trouble modeling an Airtable base that includes linked fields between several tables. The issue appears to be that I can't reference the linked object model until that model is declared, but each model has links to other tables.

A simplified instance, for example:

class TableOne(orm.Model):
     table_two = orm.fields.Linkfield("Table two", TableTwo, lazy=False)
     table_three = orm.fields.Linkfield("Table two", TableThree, lazy=False)

class TableTwo(orm.Model):
     table_one = orm.fields.Linkfield("Table one", TableOne, lazy=False)
     table_three = orm.fields.Linkfield("Table three", TableThree, lazy=False)

class TableThree(orm.Model):
     table_one = orm.fields.Linkfield("Table two", TableTwo, lazy=False)
     table_three = orm.fields.Linkfield("Table three", TableThree, lazy=False)

In which case I receive the following error on line 2 of this snippet: NameError: name 'TableTwo' is not defined

Is there a better way to approach modeling this base?

gtalarico commented 2 years ago

You are right. What I have seen done in cases like this (Django, flask) is to provide class name as a string and lazily resolve the class later.... need to think about this one.

gtalarico commented 2 years ago

Actually something like this might work @aleafa: https://stackoverflow.com/questions/3270045/python-circular-references

class A:
    ... # all fields except the circular references

class B:
    ... # all fields except the circular references

# then define the circular references:
A.b = Linkfield(..., A)
B.a = Linkfield(..., A)

If this is a serious/large application you may want to look into how and mitigation for memory leaks in circular references.

larsakerson commented 2 years ago

Thanks, @gtalarico. I had tried this, but it causes a KeyError in the Model from_record method when creating an instance. This error occurs even though the linked field is present in the record result from Airtable and the field name referenced in the model matches the Airtable field name.

Thanks for the reference re mitigating memory leaks. Definitely worth keeping in mind in situations like this.

mesozoic commented 1 year ago

This was resolved in #277; see https://pyairtable.readthedocs.io/en/stable/orm.html#linked-records