I want to generate unique codes (e.g. “DXGH”) and save it as a field in one of my models. The problem I have is that I do not know how to check against previously generated codes whenever a new object is created.
Currently my models.py looks something like this:
def code_gen(): random_string = '' for _ in range(4): random_string += chr(random.randint(97,122)) return random_string class Room(models.Model): room_code = models.CharField(default=code_gen) #other fields def __str__(self): return self.room_code #other methods def code_gen_unique(self): #I know the code below is incorrect code_list = [] for object in Room.Objects.all(): code_list.append(object.room_code) while True: temp_code = code_gen() if temp_code in code_list: continue break return temp_code
Ideally I would set the default value of room_code to code_gen_unique, but I can’t declare code_gen_unique() before my Room class, nor after it.
I expect there is a much easier solution than I have considered, and would appreciate any help very much! Cheers
Edit
Thanks to Willem Van Onsem for correcting my understanding – declaring the uniqueness-checking function before the Model, and setting the function as the default value for the room_code field does the job.
Advertisement
Answer
You can define the default generator before you define the Room
class:
def code_gen(): random_string = '' for _ in range(4): random_string += chr(random.randint(97,122)) return random_string def code_gen_unique(): code_set = set(Room.Objects.values('room_code')) while True: temp_code = code_gen() if temp_code not in code_set: return temp_code class Room(models.Model): room_code = models.CharField(default=code_gen) # …
The Room
identifier will be resolved to the Room
class, since the method will not run when defined, but when called, and it will only be called when constructing a new Room
object.