Reputation: 2893
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
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