BartoNaz
BartoNaz

Reputation: 2893

Reference field's default function in Django model's method

There is a model with a field that should be auto-populated with a fixed-length random identifier:

from django.db import models
from django.utils.crypto import get_random_string

def get_random_string_fixed():
    return get_random_string(length=20)

class Post(models.Model):
    identifier = models.CharField(unique=True, default=get_random_string_fixed)

In order to unsure that the generate value is indeed unique, I want regenerate it in the save method, if such value already exists:

def save(self, *args, **kwargs):
    if not self.pk:
        while Post.objects.filter(identifier=self.identifier).exists():
            self.identifier = get_random_string_fixed()
    super().save(*args, **kwargs)

The problem with this implementation is that get_random_string_fixed is hardcoded in the save() method. If at some point I decide to choose a different default function for this field, I'll have to change it in several places, which is a bad practice.

Is there a way of referencing the function assigned to the default attribute of a field in a model's method, without hardcoding the name of the function?

Upvotes: 0

Views: 493

Answers (1)

Kevin Christopher Henry
Kevin Christopher Henry

Reputation: 48902

Sure, you can use the introspection API to do that:

Post._meta.get_field("identifier").default

That said, I don't see much point in having a default at all. You're overriding it in save() anyway, and it's a bit misleading since it's not actually the default.

Also note that your algorithm still has failure cases. With default transaction isolation levels it won't prevent two transactions from writing the same value at the same time. Of course, that's extremely unlikely.

Upvotes: 2

Related Questions