[PonyORM-list] get PK of the record before committing it to DB

Alexander Kozlovsky alexander.kozlovsky at gmail.com
Fri Mar 27 12:32:56 UTC 2015

Hi Vadim,

When you create License object it is not necessary to specify exact value
of customer id. Since the `customer` attribute is defined as
all that is necessary is to pass the customer object when creating a new
License instance. So you can just write:

    cust = Customer(name='asd',email='asd at qwe.com')
    License(customer=cust, x=1, y=2)

The value of `customer` attribute is not customer id, but the customer
object. It does not matter that this object has no assigned id value yet.
During commit Pony will see that it is necessary to insert a new row for
this customer object, obtain new customer id and then use that id during
inserting of new license object.

Instead of the line

    License(customer=cust, x=1, y=2)

you can also write

    cust.licenses.create(x=1, y=2)

This is just the syntactic sugar.

In most cases, Pony can determine by itself the right order in which the
new rows should be inserted to the database. The only problematic situation
is when two objects have the cross-references with type of "to-one" to each
other. For example, we can have Person class with the `spouse` attribute.
This is the example of symmetric attribute, which links to itself:

    class Person(db.Entity):
        name = Required(str)
        spouse = Optional(Person, reverse='spouse')

Let's say we want to create two new objects `husband` and `wife` and store
them to the database. We cannot just do the following:

    husband = Person(name='John')
    wife = Person(name='Mary')
    husband.spouse = wife

In this situation Pony cannot insert husband to the database, because in
order to do this Pony needs to know wife id. But the same situation is with
wife - Pony cannot store it to the database without storing husband first.
In this case you will get an exception UnresolvableCyclicDependency. You
can solve this problem by saving objects explicitly before you set up the
link between them. The next code should works fine:

    husband = Person(name='John')
    wife = Person(name='Mary')
    husband.spouse = wife

The `flush()` function forces Pony to store all changed or created objects
to the database. At this moment all newly inserted objects will receive ids
from the database. Then Pony will do update of these objects in order to
establish the link between them.

So, in order to get id of the Customer object you can call `flush()`
method. But in your case this is not necessary, because you have no cyclic
relations between Customer and License. Just specify Customer as an object
and not as id, and Pony will figure out the rest.


On Fri, Mar 27, 2015 at 2:32 PM, Вадим Бажов <vadim at ideco.ru> wrote:

>  It doesn't work for me.
> I have a Customers entity with 'licences' field as Set which is in
> relation with Licences entity which have back relation field 'customer' as
> Required(Customers).
> Hence i must supply customer's id for 'customer' field while add licence
> to a customer object.
> I must do the following:
> cust = Customer(name='asd',email='asd at qwe.com') <- it doesn't create id
> before commiting it.
> lic = cust.licences.add(
>     customer=cust.id, <- required filed in DB model. related to Customers
> record by PK.
>     x=1,
>     y=2
> )
> But newly created object has no id since it wasn't written to DB yet.
> May be Pony allows child entities without Required fields linking entity
> back to a parent entity, but i didn't try it.
> On 25.03.2015 11:03, Matthew Bell wrote:
>   You don't need the PK to add a relation, you can do:
> cust = Customers(name='GazMyas',city='Chelyabinsk')
>  cust.licenses.add(License(x=1, y=2))
> cust.licenses.add(License(x=3, y=4))
>  So, create the customer, then loop over all licenses for that customer,
> doing customer.licenses.add
>  You can then commit after each iteration, or just once at the end of the
> script, up to you.
> On 25 March 2015 at 08:28, Вадим Бажов <vadim at ideco.ru> wrote:
>>  Hello happy pony users and devs !
>> I do an import from old db to a new one, driven by pony orm. Import
>> iterates over records of customers and their related licences, fetched from
>> an old DB. So we have to fill two tables in new DB: Customers table and
>> Licence table with records, which have one2many relations (one Customer can
>> have many Licences, by PK). PK is an autoincrementing integer in both
>> tables.
>> Within *each iteration* of import i need to write one Customer record
>> and its Licences records to new DB. Licence records should have customer_id
>> fields filled up with corresponding Customer PKs. Here we have a problem:
>> If we create an object of an entity Customers : cust =
>> Customers(name='GazMyas',city='Chelyabinsk') , it wont be recorded to a
>> DB exactly at this moment and we wont able to use its ID (pk of the record)
>> to bind Licence records to it. In other words there is no 'cust.id'
>> element at this moment.
>> We can do a 'commit()' each time we create a Customer object. After that '
>> cust.id' comes ready. But in case of monstrous imports with over 20 000
>> records committing every record to hdd slows down the import process to
>> hours. And hangs up your server hard drive. Anyway, it's a bad practice to
>> commit every record walking the huge array of incoming data.
>> So, by now, I fill up two dicts with Customers records, incrementing
>> their ID's manually (customer_id += 1) and Licences records bound to this
>> pre-calculated ID's. When dicts are ready, I write them to a new DB walking
>> through them.
>> Is there a better way to complete a data import without filling up
>> transition dicts and calculating autoincrement IDs by hand ? Can I somehow
>> use PKs of the records before committing them to DB ?
>> _______________________________________________
>> ponyorm-list mailing list
>> ponyorm-list at ponyorm.com
>> /ponyorm-list
> --
> Regards,
> Matthew Bell
> _______________________________________________
> ponyorm-list mailing listponyorm-list at ponyorm.comhttps://mailman-mail5.webfaction.com/listinfo/ponyorm-list
> _______________________________________________
> ponyorm-list mailing list
> ponyorm-list at ponyorm.com
> /ponyorm-list
-------------- next part --------------
An HTML attachment was scrubbed...
URL: </ponyorm-list/attachments/20150327/3e46a88a/attachment.html>

More information about the ponyorm-list mailing list