URL-friendly, random (enumeration-resistant) IDs for Django models.
This snippet only depends on the base58
package:
pip install base58 # if using PIP
poetry add base58 # if using Poetry
- Install the dependencies from above.
- Copy the contents of the fields.py file into your project (a suitable location is under your core app's models package).
- Add a
ShortUUIDField
to your models. makemigrations
,migrate
and profit!
Random UUIDs provide resistance against enumeration attacks, and Django already
provides the UUIDField
which can be easily used as a primary key. However, the
default hexadecimal representation of UUIDs used is not efficient, since each
UUID takes up 36 characters. An easy solution to this is to use a more dense
encoding, such as base 64 which is available as part of the standard library but
has the inconvenience of using hyphens (-
) which introduce breakpoints when
selecting words in most operating systems. Try double-clicking the ID below and
you'll notice that the selection automatically extends only up to the hyphen:
uGRQNvcFTUukK-Mla2UTaQ
Instead, we can use base 58 and the Bitcoin alphabet, which also eliminates ambiguous characters such as 0 and O. That encoding gives us 23-character long strings which are URL friendly and can be selected at once just by double clicking:
Q9oGv7rbFEExoSR4FFzgiL
- Python's own UUID module
- KSUID implementations: svix-ksuid and cyksuid
- ulid.py
- timeflake
- snowflake-id
- cuid2
- django-extension's own ShortUUIDField
I've probably spent way too much time thinking about IDs both from the developer and user experience perspectives, as well as from performance and security standpoints and written a couple of blog posts about it: