devfeng
devfeng

Reputation: 291

Django abstract model with flexibility to accept parameters

I have uuid field in pretty much every model. To avoid redundancy, I have this BaseUuid abstract model to generate random uuid field:

class BaseUuid(models.Model):  # base abstract model with uuid field
    class Meta:
        abstract = True

    uuid = models.CharField(max_length=22, unique=True)

    def save(self, *args, **kwargs):
        if not self.uuid:
            uuid = shortuuid.uuid()[:10]
            while self.__class__.objects.filter(uuid=uuid).exists():
                uuid = shortuuid.uuid()[:10]
            self.uuid = uuid
        super(BaseUuid, self).save(*args, **kwargs)

As one may notice, the above code has a fixed uuid lengh (10).

Now I'd like to have the flexibility to set up that length. I want something like:

class BaseUuid(models.Model):  # base abstract model with uuid field
    class Meta:
        abstract = True

    uuid = models.CharField(max_length=22, unique=True)

    def __init__(self, uuid_length=10, *args, **kwargs):
        super(BaseUuid, self).__init__(*args, **kwargs)
        self.uuid_length = 22 if uuid_length > 22 else 5 if uuid_length < 5 else uuid_length

    def save(self, *args, **kwargs):
        if not self.uuid:
            uuid = shortuuid.uuid()[:self.uuid_length]
            while self.__class__.objects.filter(uuid=uuid).exists():
                uuid = shortuuid.uuid()[:self.uuid_length]
            self.uuid = uuid
        super(BaseUuid, self).save(*args, **kwargs)

The idea is to enable uuid_length parameter:

class SomeModel(BaseUuid(uuid_length=6), SomeOtherMixin):
    ...

But it doesn't seem to work. Since the BaseUuid is subclassed from models.Model, "self.uuid_length" was treated as a model field while it is not defined.

I was wondering what other workarounds / technologies should I use? Thanks.

Upvotes: 0

Views: 261

Answers (1)

Ghopper21
Ghopper21

Reputation: 10477

Make uuid_length a class variable in the subclass, thus:

class SomeModel(BaseUuid, SomeOtherMixin):

    uuid_length = 20 // or whatever...

    ...

The reference to self.uuid_length in the save method of the base class will refer to the subclass's uuid_length as you intend.

Upvotes: 3

Related Questions