Jaymon / prom

A PostgreSQL or SQLite orm for Python
MIT License
22 stars 4 forks source link

Orm.__getattr__ refactor #176

Closed Jaymon closed 6 months ago

Jaymon commented 6 months ago

Currently, __getattr__ handles field to an instance:

class Foo(Orm):
    bar_id = Field(Bar)

f = await Foo.query.one()
b = await f.bar

And it handles the other direction also:

class Foo(Orm):
    pass

class Bar(Orm):
    foo_id = Field(Foo)

f = await Foo.query.one()
b = await f.bar
bs = await f.bars

All of the above is actually implemented in the __getattr__ method. There is a third case it doesn't handle, but I'd like it to:

class Foo(Orm):
    pass

class Bar(Orm):
    pass

class FooBar(Orm):
    foo_id = Field(Foo)
    bar_id = Field(Bar)

The lookup table. I think this should still be valid:

f = await Foo.query.one()
await f.bars

b = await Bar.query.one()
await b.foos

I'm proposing breaking all three cases into external methods and just calling those methods from __getattr__. Also adding lookup methods, probably onto schema, so __getattr__ should be something like this:

if orm_field_to_ref(name):
    return self.field_to_value(name)

elif ref_field_to_orm(name):
    return ref_field_to_value(name, getattr(self, field_name))

elif ref_lookup(name):
    return ref_fields_to_value(name)    

The ref_fields_to_value should find the Orm that matches name (by checking model_name and models_name until they match) and then finding a table that contains fields with type for the current orm and the ref orm, and querying the ref orm using a subquery on the lookup orm.