Auto-incrementing IDs are, as their name says, automatically generated for you when you insert a new row into the database. When you call , peewee determines whether to do an INSERT versus an UPDATE based on the presence of a primary key value. Since, with our uuid example, the database driver won’t generate a new ID, we need to specify it manually. When we call save() for the first time, pass in force_insert = True:

    1. # This works because .create() will specify `force_insert=True`.
    2. obj1 = UUIDModel.create(id=uuid.uuid4())
    3. # This will not work, however. Peewee will attempt to do an update:
    4. obj2 = UUIDModel(id=uuid.uuid4())
    5. obj2.save() # WRONG
    6. # Once the object has been created, you can call save() normally.
    7. obj2.save()

    Note

    Any foreign keys to a model with a non-integer primary key will have a ForeignKeyField use the same underlying storage type as the primary key they are related to.

    Warning

    Peewee does not support foreign-keys to models that define a CompositeKey primary key. If you wish to add a foreign-key to a model that has a composite primary key, replicate the columns on the related model and add a custom accessor (e.g. a property).

    Sometimes you do not want the database to automatically generate a value for the primary key, for instance when bulk loading relational data. To handle this on a one-off basis, you can simply tell peewee to turn off auto_increment during the import:

    1. data = load_user_csv() # load up a bunch of data
    2. User._meta.auto_increment = False # turn off auto incrementing IDs
    3. with db.atomic():
    4. for row in data:
    5. u = User(id=row[0], username=row[1])
    6. u.save(force_insert=True) # <-- force peewee to insert row

    If you always want to have control over the primary key, simply do not use the PrimaryKeyField field type, but use a normal IntegerField (or other column type):

    1. class User(BaseModel):
    2. id = IntegerField(primary_key=True)
    3. >>> u = User.create(id=999, username='somebody')
    4. >>> u.id
    5. 999
    6. >>> User.get(User.username == 'somebody').id
    7. 999

    If you wish to create a model with no primary key, you can specify primary_key = False in the inner Meta class:

    This will yield the following DDL:

    1. CREATE TABLE "mydata" (
    2. "timestamp" DATETIME NOT NULL,
    3. )

    Some model APIs may not work correctly for models without a primary key, for instance and delete_instance() (you can instead use , update() and ).