Search code examples
pythonpeewee

How to extend peewee to use logical deletes?


I'm using peewee as ORM for a project and want to extend it to handle logical deletes.

I've added "deleted" field to my base model and have extended the delete operations as follows:

@classmethod
def delete(cls, permanently=False):
    if permanently:
        return super(BaseModel, cls).delete()
    else:
        return super(BaseModel, cls).update(deleted=True, modified_at=datetime.datetime.now())

def delete_instance(self, permanently=False, recursive=False, delete_nullable=False):
    if permanently:
        return self.delete(permanently).where(self.pk_expr()).execute()
    else:
        self.deleted = True
        return self.save()

This works great. However, when I'm overriding select I get some problems.

@classmethod
def select(cls, *selection):
    print selection
    return super(BaseModel, cls).select(cls, *selection).where(cls.deleted == False)

This works in most cases, but in certains selects it breaks when the resulting query ends up using a join with the keyword "IN" with the following error: "1241, 'Operand should contain 1 column(s)"

Any suggestion on how to properly override select or work around this problem?


Solution

  • I always use a field on my models to indicate whether the model is deleted. I do not recommend overriding methods like delete, delete_instance and especially select. Rather create a new API and use that. Here's how I typically do it:

    class StatusModel(Model):
        status = IntegerField(
            choices=(
                (1, 'Public'),
                (2, 'Private'),
                (3, 'Deleted')),
            default=1)
    
         @classmethod
         def public(cls):
             return cls.select().where(cls.status == 1)