Created
November 21, 2013 17:15
-
-
Save jchv/7585753 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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