Search code examples
pythonmysqlormdatabase-normalizationponyorm

Pony ORM Entity Unidirectional Mapping gives an error


I have 2 tables. TableA & TableB

TableA

+------+----------------+-----------+
|  id  | some_attribute | tableB_id |
+------+----------------+-----------+

id=primary key

some_attribute=varchar

TableB_id=foreign key

TableB

+------+----------------+
|  id  | some_attribute |
+------+----------------+

id=primary key

some_attribute=varchar


My code:

# establish a connection with the database (MySQL)
db = Connection.Connection.connect_db_server_default()


class TableB(db.Entity):
    _table_ = "table_b"
    id = PrimaryKey(int, auto=False)
    some_attribute = Required(str)


class TableA(db.Entity):
    _table_ = "table_a"
    id = PrimaryKey(int, auto=False)
    some_attribute = Required(str)
    TableB_id = Set(TableA)

Gives the following error:
pony.orm.core.ERDiagramError: Reverse attribute for TableA.TableB_id not found


My Question:

How can the above relationship be recreated, using Pony ORM? Do entities always need to have bi-directional relationship?

Is there any way at all to achieve proper database normalization or will I have to use some different ORM module?


Solution

  • It looks like that the error here is my own and the answer to this is specified in the Pony-ORM documentation.

    I assumed that since TableB is independent and is the referenced table, it shouldn't have any kind of mapping from itself to TableA. Yet, the documentation specifies:

    Some mappers (e.g. Django) require defining relationships on one side only. Pony requires defining relationships on both sides explicitly (as The Zen of Python reads: Explicit is better than implicit), which allows the user to see all relationships from the perspective of each entity.

    And from the examples posted at the same section of the documentation:

    # If we want to allow an instance of OrderItem to exist without
    # being assigned to an 'Order', we can define the order attribute as Optional:
    class Order(db.Entity):
        items = Set(lambda: Order)
    
    class OrderItem(db.Entity):
        order = Optional(Order)
    

    Even though the way Pony-ORM works is completely wrong in terms of database normalization, it cannot function any other way. A module should never be blindly used, without spending some time first to properly read the documentation.

    Ethical Lesson

    NEver assume. Read your Documentation.