I have a Django web application that uses the default auto-incremented positive integers as the primary key. This key is used throughout the application and is frequently inserted into the URL. I don't want to expose this number to the public so that they can guess the number of users or other entities in my Database.
This is a frequent requirement and I have seen questions to similar mine with answers. Most solutions recommend hashing the original primary key value. However, none of those answers fit my need exactly. These are my requirements:
- I would like to keep the Primary Key field type as Integer.
- I also would prefer not to have to hash/unhash this value every time it is read or written or compared to the database. That seems wastefuly It would be nice to do it just once: When the record is initially inserted into the Database
- The hashing/encryption function need not be reversible since I don't need to recover the original sequential key. The hashed value just needs to be unique.
- The hashed value needs to be unique ONLY for that table -- not universally unique.
- The hashed value should be as short as possible. I would like to avoid extremely long (20+ characters) URLs
What is the best way to do achieve this? Would the following work?
def hash_function(int):
return fancy-hash-function # What function should I use??
def obfuscate_pk(sender, instance, created, **kwargs):
if created:
logger.info("MyClass #%s, created with created=%s: %s" % (instance.pk, created, instance))
instance.pk = hash_function(instance.pk)
instance.save()
logger.info("\tNew Pk=%s" % instance.pk)
class MyClass(models.Model):
blahblah = models.CharField(max_length=50, null=False, blank=False,)
post_save.connect(obfuscate_pk, sender=MyClass)