Skip to content

Instantly share code, notes, and snippets.

@jchv
Created November 21, 2013 17:15
Show Gist options
  • Save jchv/7585753 to your computer and use it in GitHub Desktop.
Save jchv/7585753 to your computer and use it in GitHub Desktop.
# UUIDField - a strictly binary, filterable, efficient UUID field that works with MySQL, PostgreSQL, SQLite3
# Needs a lot more testing. Current version not tested on PostgreSQL. Partially based on David Cramer's
# UUIDField, with ideas taken from django-extensions, django's BinaryField and some other places.
import uuid
from django import forms
from django.db.models import Field, SubfieldBase
# Enable native UUIDs in PostgreSQL (from dcramer/django-uuidfield)
try:
import psycopg2.extras
psycopg2.extras.register_uuid()
except (ImportError, AttributeError):
pass
# Tell SQlite to not convert uuids into strings.
try:
try:
from pysqlite2 import dbapi2 as SQLiteDatabase
except ImportError:
from sqlite3 import dbapi2 as SQLiteDatabase
except ImportError:
pass
if SQLiteDatabase:
SQLiteDatabase.register_converter("uuid", lambda s: s)
class UUIDField(Field):
description = "UUID field"
__metaclass__ = SubfieldBase
def __init__(self, auto=False, *args, **kwargs):
kwargs['max_length'] = 16
self.auto = auto
super(UUIDField, self).__init__(*args, **kwargs)
def pre_save(self, model_instance, add):
value = getattr(model_instance, self.attname, None)
if self.auto and add and not value:
uuid_ = uuid.uuid4().bytes
setattr(model_instance, self.attname, uuid_)
value = uuid_
return value
def db_type(self, connection):
if connection and ('postgres' in connection.vendor or 'sqlite' in connection.vendor):
return 'uuid'
return 'binary(16)'
def get_db_prep_value(self, value, connection, prepared=False):
if value is None:
return None
return connection.Database.Binary(value)
def value_to_string(self, obj):
if obj:
value = self._get_val_from_obj(obj)
return value
return None
def to_python(self, value):
# PostgreSQL is really smart and handles our UUIDs natively. But,
# to keep it simple, we just mash down to bytes.
if isinstance(value, uuid.UUID):
return value.bytes
return value
# For south migrations (from dcramer/django-uuidfield)
# Need to edit this for your usage.
try:
from south.modelsinspector import add_introspection_rules
add_introspection_rules([], [r"^app\.fields\.UUIDField"])
except ImportError:
pass
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment