Trying to use a custom UUID mixin for peewee does not override base AutoField ID

Viewed 656

I want to create a field mixin holding just a UUIDField, to be the primary key of any model who includes the mixin, to be used on some models, but not all (some models have their primary key defined by an external program). My hope is to have most of my models not use an AutoField for their primary key. Specifically, I'm designing a simple currency system, and I have a Wallet model, which will inherit from the BaseModel class that peewee recommends you create to initialize the database, and this UUID mixin. My problem is that when I try to database.create_tables([Wallet]), I get the following error:

peewee.ImproperlyConfigured: database attribute does not appear to be set on the model: <Model: Wallet>

My folder structure is as follows (I'll omit the __init__.py files):

models
|_ base_model.py
|_ currencies
   |_ wallet.py
|_ mixins
   |_ uuid_mixin.py

base_model.py:

db = SqliteDatabase('database.db',
                    pragmas={
                        'foreign_keys': 1,
                        'journal_mode': 'wal',
                    })


class BaseModel(Model):

    class Meta:
        database = db

uuid_mixin.py:

import uuid

from peewee import UUIDField, Model


class UUIDMixin(Model):
    id = UUIDField(primary_key=True, default=uuid.uuid4)

wallet.py:

from models import BaseModel, UUIDMixin


class Wallet(UUIDMixin, BaseModel):
    pass

I tried flipping the order of inheritance in the Wallet class to BaseModel, UUIDMixin, and the error goes away, but it results in the fields of the wallet table: {'id': <AutoField: Wallet.id>}, not the UUID I was expecting. What's wrong with my code?

1 Answers

To avoid the multiple-inheritance issues that cause this, I would just construct a separate base model, e.g.:

class BaseModel(Model):

    class Meta:
        database = db


class BaseModelWithUUID(BaseModel):
    id = UUIDField(primary_key=True, default=uuid.uuid4)


class Wallet(BaseModelWithUUID):
    pass

Also, I don't know the details of your implementation, but it's possible that a custom field, instead of model, might make more sense when dealing with currency.

Related