Issue: Postgres UUID as Primary Key, last_id not returned on save or create.
Author: Ryanb58
State: closed
Created: 2019-04-18 18:54:39

Hello, I am running python 3.7 with pee wee 3.9.3. 

My model seems to not have the primary key attached to the instance after saving the record to the database.

Setup:
```
DATABASE = PostgresqlDatabase(None)

class BaseModel(Model):
    class Meta:
        database = DATABASE

class EmailAddresses(BaseModel):
    uuid = UUIDField(constraints=[SQL("DEFAULT uuid_generate_v4()")], primary_key=True)

    account_uuid = TextField()
    created_on = DateTimeField(null=True, default=datetime.datetime.now)
    email = CharField()
    primary = BooleanField(null=True)
    verified = BooleanField(null=True)
    verified_on = DateTimeField(null=True)

    class Meta:
        table_name = 'email_addresses'
        indexes = (
            (('uuid', 'account_uuid'), True),
        )
```

I have tried this:
```
email = EmailAddresses.create(
            account_uuid= str(account_uuid),
            email= "admin@example.com",
            primary=True,
            verified=True
        )
```
and
```
email = EmailAddresses()
email.account_uuid = str(account_uuid)
email.email = "admin@example.com"
email.primary = True
email.verified = True
email.save()
```

The result each time is :
```
ipdb> email.uuid
ipdb>
```

yet when I go to the database via pgcli or adminer.. I see the record with the primary key. 
Am I missing something? Shouldn't the primary key be returned and placed on the object after I "create" or "save" the object to the database?

Historically Peewee hasn't really offered much support for fields whose defaults are generated on the server. Postgresql has a nice RETURNING clause support which we can use to obtain the server-generated values without incurring an additional query, but no such thing exists for MySQL or Sqlite at the time of writing. MySQL and Sqlite *do*, however, have APIs for obtaining the primary key of the last-inserted row when that row uses an auto-incrementing integer primary key.

So the way it worked is -- you use an auto-incrementing integer primary key (the default when declaring a peewee model), and your IDs will be populated correctly after calling save() or create().

If you are using a non-auto-incrementing ID, and the value is generated from the Python application, that's no problem. Because you are generating the ID, everything works.

However -- if you have a non-auto-incrementing ID *and* it is generated by the database server -- historically Peewee has not populated the ID after the insert.

I've made a change in 1be9f329523297cf27855c9276de3904aa968189 that will more aggressively set the primary-key on the model after insert, in the event that it is available (via RETURNING or whatever). Since Peewee already utilizes the RETURNING clause when inserting models into postgres dbs, Peewee should now be working for your use case.

```python
email = EmailAddresses.create(
            account_uuid= str(account_uuid),
            email= "admin@example.com",
            primary=True,
            verified=True)
print(email.uuid)  # will print the uuid now.
```

For the more general case of populating arbitrary model fields from the database after save, Peewee currently does not do this automatically.

If you had multiple fields that were being populated by the DB on insert, you could just use the insert + returning APIs to achieve an equivalent effect for arbitrary columns:

```python
iq = EmailAddress.insert(
  account_uuid=str(account_uuid),
  primary=True,
  verified=True).returning(EmailAddress)
# The insert+returning query returns an EmailAddress instance fully-populated:
email = list(iq.objects())[0]
```