dcramer / django-uuidfield

A UUIDField for Django
BSD 3-Clause "New" or "Revised" License
262 stars 115 forks source link

introspection rules #19

Open toudi opened 11 years ago

toudi commented 11 years ago

hello.

while googling i found the other implementation of uuidfield for django.

https://bitbucket.org/schinckel/django-uuidfield

apparently it handles the problem of migrations (to be more specific, adding a uuidfield to existing model). it boils down to introspection rules.

please refer to: http://south.aeracode.org/ticket/295#comment:8

dcramer commented 11 years ago

Feel free to submit a pull request

toudi commented 11 years ago

While i don't feel competent enought to do this ( i don't know how should it be tested) i propose a compromise: A patch and a comment.

Firstly, the patch in question:

diff --git a/uuidfield/fields.py b/uuidfield/fields.py
index e000e80..af6102a 100644
--- a/uuidfield/fields.py
+++ b/uuidfield/fields.py
@@ -131,6 +131,15 @@ class UUIDField(Field):

 try:
     from south.modelsinspector import add_introspection_rules
-    add_introspection_rules([], [r"^uuidfield\.fields\.UUIDField"])
+    add_introspection_rules([
+        (
+            [UUIDField], # Class(es) these apply to
+            [],         # Positional arguments (not used)
+            {           # Keyword argument
+                "auto": ["auto", {"default": "False"}],
+                "default": ["default", {"ignore_if": "default"}],
+            },
+        ),
+    ], ["^uuidfield\.fields\.UUIDField"])
 except ImportError:
     pass

and an explanation.

i encoutered a problem while adding uuidfield to existing model. The problem is that south does evaluate a default value into a static string, and a column uuid can't be unique.

What i have done is:

1/ add uuidfield to model 2/ ./manage.py schemamigration myapp --auto 3/ edited the migration so it resembles this:

def forwards(self, orm):
        # Adding field 'BaseTransaction.uuid'
        db.add_column(u'transaction_basetransaction', 'uuid',
                      self.gf('uuidfield.fields.UUIDField')(auto=True, unique=False, max_length=32, blank=True, null=True),
                      keep_default=False)

(note unique=False and blank=True, null=True) 4/ I've created a data migration. This is actually crutial. so ./manage.py datamigration myapp fill_in_uuid

from uuid import uuid4

class Migration(DataMigration):

    def forwards(self, orm):
        "Write your forwards methods here."
        # Note: Remember to use orm['appname.ModelName'] rather than "from appname.models..."
        for b in orm['transaction.BaseTransaction'].objects.all():
            b.uuid = str(uuid4().hex)
            b.save()

5/ i've copied migration from point 3 as a new file and did alter_column, like this:

def forwards(self, orm):
        # Adding field 'BaseTransaction.uuid'
        db.alter_column(u'transaction_basetransaction', 'uuid',
                      self.gf('uuidfield.fields.UUIDField')(auto=True, unique=True, max_length=32, blank=False, null=False),)

(note unique=True, blank=False, null=False)

As i'm not the author i have no idea whether this patch gives any solution to the problem or is it not related at all and the whole magic lies within the migrations themselves. Just wanted to help and show the pieces i have picked around google for this subject.

best regards

rikkiprince commented 9 years ago

I take it this hasn't been fixed? I bumped into the "django.db.utils.IntegrityError: UNIQUE constraint failed" error today.

Would you accept a pull request for a note in the README about this limitation?