Monday, October 23, 2017

Re: Generating a unique 10 digit ID for each model instance



On Oct 22, 2017 8:52 AM, "Jack Zhang" <valachio123@gmail.com> wrote:
Let's say I have a model called 'Dogs'.  Users can create instances of Dogs.  For every Dogs instance that is created, I want to assign a globally unique ID to it.  The ID will be 3 capitalized letters followed by 7 numbers.  E.g. ABC1234567, POZ2930193

What is the easiest way to go about doing this?  I looked into UUID but it generates a longer string.  Keep in mind that the ID must be globally unique - so after one has been created, it should not be created again.

A unique index constraint on the field will ensure that duplicate values are not allowed. There are several ways to go about doing this. Will the ID's be sequential or random? 

If sequential, all of your save operations where an ID is created should be within transaction blocks. ORM operations like .last() come in handy to determine the next available ID. 

One option to consider is splitting the ID into two model fields, one for the 3 character prefix, and the second for the numerical suffix. The "ID" would then be presented to the end user as the concatenation of the two fields. Doing this provides two advantages. Searching against a text string is slow compared to a numerical search. An ID provided by the user is then searched within the DB using the two fields after being easily split in Python, taking advantage of native type indexing in the DB. Secondly, you can choose to take advantage of the DB's auto-increment functionality on the second field. The DB is way more efficient for tracking that. Sure, it will start with 1 and work its way up, but to make a 7 digit number out of that, you just pad it with six zeros before combining it with the prefix just before you display it to the user. It wouldn't matter what the prefix value is at that point. All you would need is the 7 digit code (which would contain mostly zeros at first) to find any record. The prefix would simply be for human interpretation. This strategy does have the side affect of two prefixes never having the same suffix, meaning you'll never have an ID value of ABC0000001 and POZ0000001 at the same time. This does limit you to a total of 9,999,999 items between all of your prefixes though. 

If it will be random, then you simply have a math.random(1,10000000) function, but you'll need extra logic to determine uniqueness and handle collisions. I'd still recommend breaking it up in to two fields if you know that is always going to be the format of your ID. Keep in mind that if you go the random route, you can never delete a record once it has been created to ensure that the ID is not reused. In this case, the .exists() method is your friend, or you can use the insertion strategy I mentioned in my other thread.

-James

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscribe@googlegroups.com.
To post to this group, send email to django-users@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/CA%2Be%2BciV2kN%2BoGy3mGakH-pzZGLQt-OG4ZYPfbA2%3DSyTSk2gtYA%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.

No comments:

Post a Comment