I wrote a little helper function for generating a unique token in django models. You can call it from the save()
method of your model. It generates a candidate token using a defined function, searches the existing rows in the database for that candidate token. If it finds one, it trys again, otherwise, it returns the candidate string. Note that there is a small race condition in this, but is unlikely to occur with a token function with a sufficiently large range of outputs.
def generate_unique_token(Model,
token_field="token",
token_function=lambda: uuid.uuid4().hex[:8]):
"""
Generates random tokens until a unique one is found
:param Model: a Model class that should be searched
:param token_field: a string with the name of the token field to search in the model_class
:param token_function: a callable that returns a candidate value
:return: the unique candidate token
"""
unique_token_found = False
while not unique_token_found:
token = token_function()
# This weird looking construction is a way to pass a value to a field with a dynamic name
if Model.objects.filter(**{token_field:token}).count() is 0:
unique_token_found = True
return token
Then, you can find a unique token simply by calling
token = generate_unique_token(MyModelInstance, "token_field_name")
It even supports using other methods of generating tokens. For example, if you want to use the full uuid, you can simply call it like this:
token = generate_unique_token(MyModel, "token_field_name", lambda: uuid.uuid4().hex)