If you need to get the primary key value of a newly created object, you can do manually within the db_session() in order to get this value:

    When is called, the object is saved only inside the current session. It means it will be persisted to the database after calling commit() manually (not necessary in most cases) or automatically before leaving the current database session.

    Usually Pony saves objects in the database in the same order as they are created or modified. In some cases Pony can reorder SQL INSERT statements if this is required for saving objects. Let’s consider the following example:

    1. from pony.orm import *
    2. db = Database()
    3. class TeamMember(db.Entity):
    4. name = Required(str)
    5. team = Optional('Team')
    6. class Team(db.Entity):
    7. name = Required(str)
    8. team_members = Set(TeamMember)
    9. db.bind('sqlite', ':memory:')
    10. db.generate_mapping(create_tables=True)
    11. set_sql_debug(True)
    12. with db_session:
    13. john = TeamMember(name='John')
    14. mary = TeamMember(name='Mary')
    15. team = Team(name='Tenacity', team_members=[john, mary])
    1. "id" INTEGER PRIMARY KEY AUTOINCREMENT,
    2. )
    3. CREATE TABLE "TeamMember" (
    4. "id" INTEGER PRIMARY KEY AUTOINCREMENT,
    5. "name" TEXT NOT NULL,
    6. "team" INTEGER REFERENCES "Team" ("id")
    7. )

    When Pony creates john, mary and team objects, it understands that it should reorder SQL INSERT statements and create an instance of the Team object in the database first, because it will allow using the team id for saving TeamMember rows:

    Cyclic chains during saving objects

    Now let’s say we want to have an ability to assign a captain to a team. For this purpose we need to add a couple of attributes to our entities: Team.captain and reverse attribute TeamMember.captain_of

    1. class TeamMember(db.Entity):
    2. name = Required(str)
    3. team = Optional('Team')
    4. captain_of = Optional('Team')
    5. class Team(db.Entity):
    6. name = Required(str)
    7. team_members = Set(TeamMember)
    8. captain = Optional(TeamMember, reverse='captain_of')

    And here is the code for creating entity instances with a captain assigned to the team:

    1. with db_session:
    2. john = TeamMember(name='John')
    3. mary = TeamMember(name='Mary')
    4. team = Team(name='Tenacity', team_members=[john, mary], captain=mary)

    Why did it happen? Let’s see. Pony sees that for saving the john and mary objects in the database it needs to know the id of the team, and tries to reorder the insert statements. But for saving the object with the captain attribute assigned, it needs to know the id of mary object. In this case Pony cannot resolve this cyclic chain and raises an exception.

    In order to save such a cyclic chain, you have to help Pony by adding the flush() command:

    1. john = TeamMember(name='John')
    2. mary = TeamMember(name='Mary')
    3. flush() # saves objects created by this moment in the database
    4. team = Team(name='Tenacity', team_members=[john, mary], captain=mary)

    In this case, Pony will save the john and mary objects in the database first and then will issue SQL UPDATE statement for building the relationship with the team object:

    1. INSERT INTO "TeamMember" ("name") VALUES (?)
    2. [u'John']
    3. INSERT INTO "TeamMember" ("name") VALUES (?)
    4. [u'Mary']
    5. INSERT INTO "Team" ("name", "captain") VALUES (?, ?)
    6. [u'Tenacity', 2]
    7. UPDATE "TeamMember"
    8. SET "team" = ?
    9. WHERE "id" = ?
    10. [1, 2]
    11. UPDATE "TeamMember"
    12. SET "team" = ?
    13. WHERE "id" = ?