devfeng
devfeng

Reputation: 291

Django abstract model inheritance

In a model I usually put a "uuid" field for friendly URI, also a "slug" field.

Say I have a model named "SomeModel", by overriding its save() method, I can generate a uuid and a slug when it's being saved:

class SomeModel(models.Model):
    ...
    def save(self, *args, **kwargs):
        if not self.uuid:
            uuid = shortuuid.uuid()[:10]
            while SomeModel.objects.filter(uuid=uuid).exists():
                uuid = shortuuid.uuid()[:10]
            self.uuid = uuid
        if not self.slug:
            self.slug = slugify(self.title)[:500].rstrip('-')
        super(SomeModel, self).save(*args, **kwargs)

It works well on regular model. Now I'd like to have an abstract model:

class SomeAbstractModel(models.Model):
    class Meta:
        abstract = True
    def save(self, *args, **kwargs):
        ...

And then:

class SomeModel(SomeAbstractModel):
    class Meta(SomeAbstractModel.Meta):
        ...

The problem is, in the abstract model, looks like I cannot just simply replace

while SomeModel.objects.filter(uuid=uuid).exists():

with

while SomeAbstractModel.objects.filter(uuid=uuid).exists():

because abstract model doesn't have a manager.

I was wondering in this case, how can I avoid having redundant code in all models' save() methods. Also I'm not sure if

while SomeModel.objects.filter(uuid=uuid).exists():

is the best practice to check if an uuid exists or not.

Upvotes: 1

Views: 710

Answers (2)

schacki
schacki

Reputation: 9533

When you create SomeModel(SomeAbstractModel), just create the class Meta from scratch without inheriting. By inheriting vom SomeAbstractModel.Meta you make it abstract again, and you cannot query on abstract model, not because they have no manager, but because there are no tables created.

So either you do this:

class SomeModel(SomeAbstractModel):
    ...
    class Meta(SomeAbstractModel.Meta):
        abstract=False
        ... your other model specific options

Or you do this (if you do not have any other model specific options:

class SomeModel(SomeAbstractModel):
    ...

Upvotes: -1

Tommaso Barbugli
Tommaso Barbugli

Reputation: 12031

Not sure if it is the prettiest way in town but this should work:

while self.__class__.objects.filter(...):
    pass

Upvotes: 3

Related Questions