9👍
Here you go
import random
import string
''.join(random.choice(string.digits) for _ in range(8))
Even shorter with python 3.6 using random.choices()
import random
import string
''.join(random.choices(string.digits, k=8))
Avoid Possible Collision:
Try creating a new object with generated id except integrity error, create id again.
eg. –
def create_obj():
id = ''.join(random.choices(string.digits, k=8))
try:
MyModel.objects.create(id=id)
except IntegrityError:
create_obj()
OR
def create_unique_id():
return ''.join(random.choices(string.digits, k=8))
def create_object():
id = create_unique_id()
unique = False
while not unique:
if not MyModel.objects.get(pk=id):
unique = True
else:
id = create_unique_id()
MyModel.objects.create(id=id)
Thanks to @WillemVanOnsem for pointing out the chances of generating duplicate id, the two examples I provided will create a new id as many times as required to get an unique id, but as the number of rows in your database increase the time to get a unique id will grow more and more and a time will come when there are so many records in your database(10^8) when creation of new record is not possible with a 8-digit uid as all possible combination already exists then you will be stuck in an infinite loop while trying to create a new object.
If the stats provided my Willem is correct, I say the changes are too high of a collision. So I would recommend not to create id’s yourself, go with django’s default auto field or uuid which guarantees uniqueness through space and time.
2👍
Assuming you are using MYSQL and your comment said you didn’t use database PK because they start with 1, 2…
Why not just make PK starts with your range?
eg.
ALTER TABLE user AUTO_INCREMENT = 10000000;
And you can put this into your custom migration, see manage.py makemigrations --empty
I presume other databases have the similar approach as well
1👍
For django app I would suggest using get_random_string from django.utils.crypto package. Internally python secrets.choice is used. This way you will not have to change code, if secrets interface changes.
from django.utils.crypto import get_random_string
def generate_account_id():
return get_random_string(8, allowed_chars='0123456789')
- [Django]-Caught TypeError while rendering: 'BoundField' object is not iterable
- [Django]-Django app not found despite adding to INSTALLED_APPS?
- [Django]-Django SQLite foreign key mismatch error
- [Django]-How to copy and change a property of many models from a queryset, in batch?
- [Django]-MySQL Query error when run within Python but not when run directly
0👍
If you work with python >= 3.6 , the alternative is secrets.token_hex(nbytes)
which returns string of hex value, then convert the string to number. To further detect collision you can also check whether any instance with the ID already exists in your Django model (as shown in the accepted answer)
code example :
import secrets
hexstr = secrets.token_hex(4)
your_id = int(hexstr, 16)
- [Django]-Django manage.py raising ImproperlyConfigured error
- [Django]-Django, set initial data to formset with ManyToMany
- [Django]-Nginx/gunicorn connection hanging for 60 seconds