Skip to content

Instantly share code, notes, and snippets.

@tveastman
Created July 10, 2019 22:46
Show Gist options
  • Save tveastman/4114f1bf7777c1a252777f4305cdb1f0 to your computer and use it in GitHub Desktop.
Save tveastman/4114f1bf7777c1a252777f4305cdb1f0 to your computer and use it in GitHub Desktop.
Here's an example of how I've used HashIds to create a non-numeric identifier for Django models based on their `id`.
import hashids
class HashidsMixin(object):
"""Add a unique 'identifier' mapped from the 'id' field of a django model."""
# Updating this salt would change every identifier for all instances of
# every model. This is probably a bad idea, so it should probably never
# ever change. It's not used for security -- just a little bit of extra
# obfuscation to the numbering.
__HASHIDS_SALT = "20OGoZ5KsC"
@classmethod
def __hashids(cls):
if not hasattr(cls, "__hashid_instance"):
cls.__hashids_instance = hashids.Hashids(
# We stick to the plain alphabet because we can't risk
# having identifiers that start with numerals (I think
# It'd break somebody's rules somewhere).
alphabet="abcdefghijklmnopqrstuvwxyz",
# Tagging the class name onto the salt guarantees that
# the counting system is different for each class.
salt=cls.__HASHIDS_SALT + cls.__name__,
# Four seems reasonable, it'll be a long time before it
# jumps to five digits, and the identifiers look 'meaty'
# which adds to their inscrutability
min_length=4,
)
return cls.__hashids_instance
@classmethod
def decode_identifier(cls, string):
"""Decode the integer from an identifier.
>>> app.models.MyModel.decode_identifier('asnf')
1
Although hashids lets you encode multiple ids, we always assume
we're only receiving exactly one, and anything else will be
ignored.
"""
ids = cls.__hashids().decode(string)
return None if len(ids) != 1 else ids[0]
@property
def identifier(self):
return self.__hashids().encode(self.id)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment