I would recommend to you the same approach that is used by Instagram. Their requirements seems to closely follow yours.
Generated IDs should be sortable by time (so a list of photo IDs, for
example, could be sorted without fetching more information about the
photos) IDs should ideally be 64 bits (for smaller indexes, and better
storage in systems like Redis) The system should introduce as few new
‘moving parts’ as possible—a large part of how we’ve been able to
scale Instagram with very few engineers is by choosing simple,
easy-to-understand solutions that we trust.
They came up with a system that has 41 bits based on the timestamp, 13 o the database shard and 10 for an auto increment portion. Sincce you don’t appear to be using shards. You can just have 41 bits for a time based copmonent and 23 bits chosen at random. That does produce an extremely unlikely 1 in 8.3 million chance of getting a conflict if you insert records at the same time. But in practice you are never likely to hit this. Right so how about some code:
START_TIME = a constant that represents a unix timestamp
inspired by http://instagram-engineering.tumblr.com/post/10853187575/sharding-ids-at-instagram
t = int(time.time()*1000) - START_TIME
u = random.SystemRandom().getrandbits(23)
id = (t << 23 ) | u
t = id >> 23
return t + START_TIME
START_TIME in the above code is some arbitary starting time. You can use time.time()*1000 , get the value and set that as
Notice that the
reverse_id method I have posted allows you to find out at which time the record was created. If you need to keep track of that information you can do so without having to add another field for it! So your primary key is actually saving your storage rather than increasing it!
Now this is what your model would look like.
id = models.BigIntegerField(default = fields.make_id, primary_key=True)
If you make changes to your database outside django you would need to create the equivalent of
make_id as an sql function
As a foot note. This is somewhat like the approach used by Mongodb to generate it’s _ID for each object.
You need to separate two concerns:
The primary key, currently an auto-incrementing integer, is the best choice for a simple, relatively predictable unique identifier that can be enforced on the database level.
That does not mean you have to expose it to users in your URLs.
I’d recommend adding a new UUID field to your model, and remapping your views to use it, instead of the PK, for object lookups.
A really simple solution is simply encrypting the ID before sending it out to an external source. You can decrypt it on the way back in.
- Traversing multiple lists in django template in same for loop
- Soft deleting objects in django
- Creating a MIME email template with images to send with python / django
- Django-tagging or django-taggit, or something else?
AUTO_INCREMENT, but pass it around in a semi-secret way: In a cookie. It takes a bit of coding to establish the cookie, set it, and read it. But cookies are hidden from all but serious hackers.
- How do you rollback during Django shell session after causing DatabaseError?
- How do I set HttpOnly cookie in Django?
- How should I validate HTML in Django templates during the development process?
- Django with NoSQL database