Как связать один атрибут сущности пониорм с несколькими другими сущностями? - PullRequest
0 голосов
/ 12 апреля 2019

Я начинаю работать с существующей базой данных, где атрибут foo таблицы A связан с несколькими другими таблицами B.foo и C.foo.Как мне сформировать эти отношения в пониоме?

База данных организована, как показано ниже.

from pony import orm
db = orm.Database()

class POI(db.Entity):
    '''Point of interest on a map'''
    name = orm.PrimaryKey(str)
    coordinateID = orm.Optional(('cartesian', 'polar')) # doesn't work ofc

class cartesian(db.Entity):
    coordinateID = orm.Required(POI)
    x = orm.Required(float)
    y = orm.Required(float)

class polar(db.Entity):
    coordinateID = orm.Required(POI)
    r = orm.Required(float)
    phi = orm.Required(float)

Конечно x, y из cartesian и r, phi из polar можно переместить в POI, и в базе данных, с которой я работаю, такая же ситуация.Но таблицы разделены между заинтересованными сторонами (cartesian и polar в этом примере), и я все равно не могу изменить схему.Я не могу разделить coordinateID в схеме (но было бы неплохо иметь разные атрибуты класса python).

1 Ответ

1 голос
/ 13 апреля 2019

Невозможно связать один атрибут для нескольких объектов в PonyORM, за исключением случая, когда эти объекты наследуются от одного и того же базового объекта, тогда вы можете указать базовый объект в качестве типа атрибута и использовать любой из унаследованных объектов в качестве действительного типа.

Если вы используете существующую схему, которую вы не можете изменить, вы, вероятно, не сможете использовать наследование и должны указать необработанный атрибут id вместо отношения:

from pony import orm
db = orm.Database()

class POI(db.Entity):
    _table_ = "table_name"
    name = orm.PrimaryKey(str)
    coordinate_id = orm.Optional(int, column="coordinateID")

class Cartesian(db2.Entity):
    _table_ = "cartesian"
    id = orm.PrimaryKey(int, column="coordinateID")
    x = orm.Required(float)
    y = orm.Required(float)

class Polar(db2.Entity):
    _table_ = "polar"
    id = orm.PrimaryKey(int, column="coordinateID")
    r = orm.Required(float)
    phi = orm.Required(float)

И тогда вы можете выполнять такие запросы:

left_join(poi for poi in POI
              for c in Cartesian
              for p in Polar
              if poi.coordinate_id == c.id
                 and poi.coordinate_id = p.id
                 and <some additional conditions>)

Обратите внимание, что все объекты, используемые в одном запросе, должны быть из одной базы данных. Если объекты принадлежат двум разным базам данных, вы не можете использовать их в одном запросе. И нужно выдавать отдельные запросы:

with db_session:
    poi = POI.get(id=some_id)
    coord = Cartesian.get(id=poi.coordinate_id)
    if coord is None:
        coord = Polar.get(id=poi.coordinate_id)
    <do something with poi and coord>

Но в случае, например, SQLite, вы можете присоединить одну базу данных к другой, чтобы они выглядели как одна база данных.

...