"""To recreate the error, just start an app and drop in this file.
Pull up the admin interface. And add a Book.  You can go ahead and add
one or more Authors at the same time.  Save your changes.

This should work with no errors.  The error occurs when you save a Book
object in the Admin interface that has one or more Authors assigned to it.

That is, after creating a Book with one or more Authors and saving it, go back
and edit that Book again in the admin interface.  Don't have to change
anything, just click Save and this is the error that is generated:


KeyError at /admin/uuid_test/book/6b31461e-ffa2-11dd-be8a-0019dbb65276/

None

Request Method:     POST
Request URL:        http://localhost:8000/admin/uuid_test/book/6b31461e-ffa2-11dd-be8a-0019dbb65276/
Exception Type:     KeyError
Exception Value:    None

Exception Location: /usr/local/lib/python2.5/site-packages/django/forms/models.py in save_existing_objects, line 411
Python Executable:  /usr/bin/python
Python Version:     2.5.2
Python Path:        [...]
Server time:        Fri, 20 Feb 2009 17:03:31 -0600
"""
from django.db import models
from django.db.models import CharField
from django.contrib import admin
try:
    import uuid
except ImportError:
    from django_extensions.utils import uuid

# UUIDVersionError and UUIDField are taken directly from the django-extensions
# project with no alterations.  I bundled them in this little test case
# so you wouldn't have to install django-extensions just to run the test.
class UUIDVersionError(Exception):
    pass

class UUIDField(CharField):
    """ UUIDField

    By default uses UUID version 1 (generate from host ID, sequence number and current time)

    The field support all uuid versions which are natively supported by the uuid python module.
    For more information see: http://docs.python.org/lib/module-uuid.html
    """

    def __init__(self, verbose_name=None, name=None, auto=True, version=1, node=None, clock_seq=None, namespace=None, **kwargs):
        kwargs['max_length'] = 36
        if auto:
            kwargs['blank'] = True
            kwargs.setdefault('editable', False)
        self.auto = auto
        self.version = version
        if version==1:
            self.node, self.clock_seq = node, clock_seq
        elif version==3 or version==5:
            self.namespace, self.name = namespace, name
        CharField.__init__(self, verbose_name, name, **kwargs)

    def get_internal_type(self):
        return CharField.__name__

    def create_uuid(self):
        if not self.version or self.version==4:
            return uuid.uuid4()
        elif self.version==1:
            return uuid.uuid1(self.node, self.clock_seq)
        elif self.version==2:
            raise UUIDVersionError("UUID version 2 is not supported.")
        elif self.version==3:
            return uuid.uuid3(self.namespace, self.name)
        elif self.version==5:
            return uuid.uuid5(self.namespace, self.name)
        else:
            raise UUIDVersionError("UUID version %s is not valid." % self.version)

    def pre_save(self, model_instance, add):
        if self.auto and add:
            value = unicode(self.create_uuid())
            setattr(model_instance, self.attname, value)
            return value
        else:
            value = super(UUIDField, self).pre_save(model_instance, add)
            if self.auto and not value:
                value = unicode(self.create_uuid())
                setattr(model_instance, self.attname, value)
        return value


class Book(models.Model):
    id = UUIDField(primary_key=True, auto_created=False)
    title = models.CharField(max_length=128)
    def __unicode__(self):
        return unicode(self.title)

class Author(models.Model):
    id = UUIDField(primary_key=True, auto_created=False)
    book = models.ForeignKey(Book)
    name = models.CharField(max_length=128)
    def __unicode(self):
        return unicode(self.name)


class AuthorInlineAdmin(admin.TabularInline):
    model=Author

class BookAdmin(admin.ModelAdmin):
    inlines = (AuthorInlineAdmin, )
admin.site.register(Book, BookAdmin)
