Skip to content

Instantly share code, notes, and snippets.

@adamJLev
Created June 5, 2015 18:43
Show Gist options
  • Save adamJLev/c738df9e7cbde61368d7 to your computer and use it in GitHub Desktop.
Save adamJLev/c738df9e7cbde61368d7 to your computer and use it in GitHub Desktop.
Stripe-style short alphanumeric UUID fields
from django.db.models import SubfieldBase
from django.core.exceptions import ImproperlyConfigured
from django_extensions.db.fields import ShortUUIDField
class XidField(ShortUUIDField):
"""
XID stands for external ID.
Randomly generated IDs (base62 encoded UUID) used for public display purposes.
The random ID gets a short textual prefix for improved legibility, like Stripe's IDs.
Example:
With prefix "usr", the db value "uUM7gxtMEGhMvMooWHj9yH" becomes "usr_uUM7gxtMEGhMvMooWHj9yH"
"""
__metaclass__ = SubfieldBase
def __init__(self, prefix=None, *args, **kwargs):
self.prefix = prefix
if not self.prefix:
raise ImproperlyConfigured("prefix parameter is required.")
kwargs.setdefault('max_length', 22)
kwargs.setdefault('unique', True)
kwargs.setdefault('verbose_name', 'XID')
kwargs.setdefault('editable', False)
super(XidField, self).__init__(*args, **kwargs)
def to_python(self, value):
"""
Adds prefix
"""
if value is not None and '_' not in value:
value = u'%s_%s' % (self.prefix, value)
return value
def get_prep_value(self, value):
"""
Remove prefix before sending to db
"""
if value is not None and '_' in value:
value = value.split('_')[1]
return value
def clean(self, value, model_instance):
"""
Override clean to use get_prep_value instead of to_python, since we do string manipulation there.
"""
value = self.get_prep_value(value)
self.validate(value, model_instance)
self.run_validators(value)
return value
def south_field_triple(self):
"""Returns a suitable description of this field for South."""
from south.modelsinspector import introspector
field_class = self.__module__ + "." + self.__class__.__name__
args, kwargs = introspector(self)
return (field_class, args, dict(kwargs.items() + { "prefix": "'%s'" % self.prefix}.items()))
def deconstruct(self):
name, path, args, kwargs = super(XidField, self).deconstruct()
kwargs["prefix"] = self.prefix
return name, path, args, kwargs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment