Skip to main content

Fancy ID fields for django models.

Project description

django-spicy-id

A drop-in replacement for Django's AutoField that gives you "Stripe-style" self-identifying string object IDs, like user_1234.

Status: Experimental! No warranty. See LICENSE.txt.

Test status

What is a "spicy" id?

It's a made-up name (because I couldn't think of a better one) for a numeric primary keys type that is shown and manipulated as a string, prefixed with a constant value.

Here are some examples. You can use this library to make your Django row IDs look like:

  • user_1234
  • account-00000000deadbeef
  • bloop:1a2k3841x

Although you should always treat these values as opaque and never decode or parse the string's contents elsewhere (see Errors), you can think of every spicy id as being composed of:

<prefix> <separator> <encoded_value>
  • prefix: A fixed string value that will be the same for all IDs of this record type, forever.
  • separator: A configurable separator which, like prefix, is fixed forever; usually _ (the default) or - (another popular choice).
  • encoded_value: The numeric portion of the id. This library supports using base 16 (hex) or base 62.

Importantly, the underlying database value is still stored and retrieved as a numeric type, just like an AutoField, SmallAutoField, or BigAutoField.

Why use spicy ids?

Briefly: Because they're so much nicer for humans to work with.

  • Readability: While row-level primary keys are typically treated as "anonymous" (as in "not something anyone should have to care about"), the fact is these values still show up in lots of situations: They're in URLs, dumped in logfiles, shown in queries, and so on. In these situations, it's just plain faster to understand "what am I looking at" when the identifier itself tells you its type.
  • Conflict and accident prevention: When your systems require you to pass around typed identifiers like acct_1234 and invoice_5432beef, certain kinds of accidents become impossible. For example, HTTP DELETE /users/invoice_21 fails fast.
  • Future-proofing: Adopting spicy IDs means your systems and APIs are developed to accept a basically-opaque string as an ID. While their underlying type is numeric, in very advanced situations you may be able to migrate to a different type or datastore "behind" the abstraction the string ID creates.

For a more detailed look at this pattern, see Stripe's "Object IDs: Designing APIs for Humans".

Usage

Given the following example model:

from django.db import models
from django_spicy_id.fields import SpicyBigAutoField

class User(models.model):
    id = SpicyBigAutoField(primary_key=True, prefix='usr')

Example usage:

>>> u = models.User.objects.create()
>>> u.id
'usr_1'
>>> u2 = models.User.objects.create(id=123456789)
>>> u2.id
'usr_8M0kX'
>>> found_user = models.User.objects.filter(id='usr_8M0kX').first()
>>> found_user == u2
True

Field types

  • SpicyBigAutoField: A spicy id which is backed by a BigAutoField (i.e. 64-bit int) column.
  • SpicyAutoField: A spicy id which is backed by a AutoField (i.e. 32-bit int) column.
  • SpicySmallAutoField: A spicy id which is backed by a SmallAutoField (i.e. 16-bit int) column.

Required Parameters

The following parameters are required at declaration:

  • prefix: The prefix to use in the encoded form. Typically this is a short, descriptive string, like user or acct and similar. Note: This library does not ensure the string you provide is unique within your project. You should ensure of that.

Optional Parameters

In addition to all parameters you can provide a normal AutoField, each of the field types above supports the following additional optional paramters:

  • sep: The separator character. Defaults to _. Can be any string.
  • encoding: What numeric encoding scheme to use. One of fields.ENCODING_BASE_62, fields.ENCODING_BASE_58, or fields.ENCODING_HEX.
  • pad: Whether the encoded portion of the id should be zero-padded so that all values are the same string length. Either False (default) or True.
    • Example without padding: user_8M0kX
    • Example with padding: user_0000008M0kX
  • randomize: If True, the default value for creates will be chosen from random.randrange(). If False (the default), works just like a normal AutoField i.e. the default value comes from the database upon INSERT.

Warning: Changing prefix, sep, pad, or encoding after you have started using the field is a breaking change. IDs generated with a different configuration will be rejected. You should not do this.

Errors

The field will throw django_spicy_id.errors.MalformedSpicyIdError, a subclass of ValueError, when an "illegal" string is provided. Note that this error can happen at runtime.

Some examples of situations that will throw this error:

  • Querying a spicy id with the wrong prefix or separator (e.g id="acct_1234 where id=invoice_1234 is expected).
  • Using illegal characters in the string.
  • Providing an unpadded value when padding is enabled.
  • Providing a padded value when padded is disabled.

Take special note of the last two errors: Regardless of field configuration the string value a spicy id yields must always be treated as an exact value. Just like you would never modify a UUID4, a spicy id string should never be translated, re-interpreted, or changed by a client.

Installation

Requirements

This package supports and is tested against the latest patch versions of:

  • Python: 3.8, 3.9, 3.10, 3.11
  • Django: 2.2, 3.1, 4.1
  • MySQL: 5.7, 8.0
  • PostgreSQL: 9.5, 10, 11, 12
  • SQLite: 3.9.0+

All database backends are tested with the latest versions of their drivers. SQLite is also tested on GitHub Actions' latest macOS virtual environment.

Instructions

Coming soon: pypi distribution. Then you will be able to do...

pip install django_spicy_id

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

django-spicy-id-0.2.1.tar.gz (8.9 kB view details)

Uploaded Source

Built Distribution

django_spicy_id-0.2.1-py3-none-any.whl (8.6 kB view details)

Uploaded Python 3

File details

Details for the file django-spicy-id-0.2.1.tar.gz.

File metadata

  • Download URL: django-spicy-id-0.2.1.tar.gz
  • Upload date:
  • Size: 8.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.2 CPython/3.11.0

File hashes

Hashes for django-spicy-id-0.2.1.tar.gz
Algorithm Hash digest
SHA256 795c735032c2674115f017c4b11352cf6c004398de77b098b078669ddb8b6449
MD5 8385b0518755f902f8b1852652e0712a
BLAKE2b-256 92b78fa85b31e16dc6e0c65d43c138cfcece8126c54d55555020a3f871d6bee6

See more details on using hashes here.

File details

Details for the file django_spicy_id-0.2.1-py3-none-any.whl.

File metadata

File hashes

Hashes for django_spicy_id-0.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 fac2bddca1d58602b3622fb37d485ef665d2bd827be2b60e5f6815bb70182086
MD5 fd3592c0110e3b710fe1bcfab64fc3bc
BLAKE2b-256 afbc56f899cfbaa493737b1c9d10a7a3133bda86ce6d4b7fb8b7c85322c8d5c5

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page