0

All I want is to generate a unique code preferably a mix of both letters and numbers when I create a Model Class called Competition in django. I want to use this code as a reference code for users to be able to fill in a form that will allow them to join that specific Competition.

I have this code in my models.py:

class Competition(models.Model):
    name = models.CharField(max_length=100)
    location = models.CharField(max_length=50)
    no_of_rounds = models.IntegerField(validators= [MinValueValidator (1, message='Please enter a number greater than or equal to 1'), MaxValueValidator (30, message='Please enter a number less than or equal to 30')])
    gates_per_round = models.IntegerField(validators= [MinValueValidator (1), MaxValueValidator (30)])
    ref_code = models.CharField(
           max_length = 10,
           blank=True,
           editable=False,
           unique=True,
           default=get_random_string(10, allowed_chars=string.ascii_uppercase + string.digits)
    )

    def __str__(self):
        return self.name

Preferably I don't want the unique code field to be a primary key if possible and that's why I have that field called ref_code. I tried creating a competition, which generated me this code LZDMGOQUFX. I am also wondering why the code only consists of letters. Anyways I tried creating a different competition but it raises an IntegrityError that says UNIQUE constraint failed in my ref_code field. Someone send help, thanks.

  • I believe the `get_random_string` call gets executed once when the model is defined, then the same `ref_code` is used every time you create an instance of `Competition`, thus violating the *unique* constraint. – Fractalism Mar 11 '23 at 19:07
  • Does this answer your question? [How to set a Django model field's default value to a function call / callable (e.g., a date relative to the time of model object creation)](https://stackoverflow.com/questions/12649659/how-to-set-a-django-model-fields-default-value-to-a-function-call-callable-e) – Fractalism Mar 11 '23 at 19:09
  • You might be interested in a variation of shortuuid (https://github.com/skorokithakis/shortuuid) – AMG Mar 12 '23 at 17:24

1 Answers1

1

In the original code get_random_string is executed on app start and used as a static value for all other models. @Fractalism in his comment pointed one way to do it, second is to overwrite save method


def save(self, *args, **kwargs):
    if not self.pk: # its a first save
        self.ref_code = get_random_string(10, allowed_chars=string.ascii_uppercase + string.digits)
    return super.save(*args, **kwargs)
jacoor
  • 760
  • 5
  • 9
  • Thank you for your help! Just leaving it here tho for people to know, when returning make sure you call the save method of the parent like so: return super(Competition, self).save(*args, **kwargs) – f-gallagher Mar 12 '23 at 11:26
  • If that worked for you please accept answer. As for save, here is docs on how to extend: https://docs.djangoproject.com/en/4.1/ref/models/instances/#customizing-model-loading Look at how they overload `save` method. No need to call `Competition` again - it only makes code more complicated. – jacoor Mar 13 '23 at 12:15