My model has a CharField
that defaults to a randomly generated string which should be unique. I don't want to use a UUIDField
. Is there a way to override the save method to handle IntegrityError
raised if the code generated is a duplicate? Or should I check for that in my generation function?
MODEL
class Item(models.Model):
...
item_code = models.CharField(max_length=11, default=get_generated_code, unique=True)
FUNCTION
def get_generated_code():
code = ''.join(random.SystemRandom().choice(string.ascii_letters + string.digits) for _ in range(11))
return code
This is what I ended up doing.
I overrode the save method such that the code is set within there and checks for integrity errors, which only raises it after 3 unsuccessful tries. As the chances of a collision are small enough, especially after 3 consecutive tries, I feel like this is a sufficient solution rather than making multiple database queries in alternative solutions.
class Item(models.Model):
...
# blank = True as this is handled by save method
code = models.CharField(max_length=11, blank=True, unique=True)
def save(self, *args, **kwargs):
if not self.code:
self.code = get_generated_code()
success = False
errors = 0
while not success:
try:
super(Item, self).save(*args, **kwargs)
except IntegrityError:
errors += 1
if errors > 3:
# tried 3 times, no dice. raise the integrity error and handle elsewhere
raise
else:
self.code = get_generated_code()
else:
success = True
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With