django-pgfields
django-pgfields copied to clipboard
Django 1.7 model UUIDField - problem with admin inlines / migrations
Hi,
I'm testing django-pgfields 1.5.0a1 with Django 1.7rc2 and I have a problem with admin inlines. These are my models:
class Elf(models.Model):
id = models.UUIDField(auto_add=True, primary_key=True)
name = models.CharField(max_length=50)
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
class RelatedToElf(models.Model):
id = models.UUIDField(auto_add=True, primary_key=True)
name = models.CharField(max_length=50)
elf = models.ForeignKey(Elf, related_name="elfs")
And here's my admin configuration:
class RelatedElfInline(admin.TabularInline):
model = models.RelatedToElf
class ElfAdmin(admin.ModelAdmin):
inlines = [RelatedElfInline,]
admin.site.register(models.Elf, ElfAdmin)
As you might notice, in the models definition I dont have default=uuid.uuid4 on the id fields but I do have auto_add=True. This is because setting a default on these fields seems to be causing inline rows in the admin to be pre-filled with the uuid4 values when the form is rendered.
When the form is saved, Django marks these inlines as 'changed' effectively trying to create them as new objects thus triggering form validation for all of these inlines requireing values for all form fields that doesn't have null=True, blank=True (e.g. "name" in this case). This happens even if the id field is hidden.
With the models' definition mentioned above inlines work well, but when I try to apply a migration, this is the result (I've applied it once with default=uuid.uuid4 and then removed it):
Running migrations:
Applying myapp.0002_auto_20140730_0000...Traceback (most recent call last):
File "manage.py", line 10, in <module>
execute_from_command_line(sys.argv)
File "/home/user/ve/myproject/local/lib/python2.7/site-packages/django/core/management/__init__.py", line 385, in execute_from_command_line
utility.execute()
File "/home/user/ve/myproject/local/lib/python2.7/site-packages/django/core/management/__init__.py", line 377, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/home/user/ve/myproject/local/lib/python2.7/site-packages/django/core/management/base.py", line 288, in run_from_argv
self.execute(*args, **options.__dict__)
File "/home/user/ve/myproject/local/lib/python2.7/site-packages/django/core/management/base.py", line 337, in execute
output = self.handle(*args, **options)
File "/home/user/ve/myproject/local/lib/python2.7/site-packages/django/core/management/commands/migrate.py", line 160, in handle
executor.migrate(targets, plan, fake=options.get("fake", False))
File "/home/user/ve/myproject/local/lib/python2.7/site-packages/django/db/migrations/executor.py", line 63, in migrate
self.apply_migration(migration, fake=fake)
File "/home/user/ve/myproject/local/lib/python2.7/site-packages/django/db/migrations/executor.py", line 97, in apply_migration
migration.apply(project_state, schema_editor)
File "/home/user/ve/myproject/local/lib/python2.7/site-packages/django/db/migrations/migration.py", line 107, in apply
operation.database_forwards(self.app_label, schema_editor, project_state, new_state)
File "/home/user/ve/myproject/local/lib/python2.7/site-packages/django/db/migrations/operations/fields.py", line 131, in database_forwards
schema_editor.alter_field(from_model, from_field, to_field)
File "/home/user/ve/myproject/local/lib/python2.7/site-packages/django/db/backends/schema.py", line 509, in alter_field
self._alter_field(model, old_field, new_field, old_type, new_type, old_db_params, new_db_params, strict)
File "/home/user/ve/myproject/local/lib/python2.7/site-packages/django/db/backends/schema.py", line 610, in _alter_field
new_default = self.effective_default(new_field)
File "/home/user/ve/myproject/local/lib/python2.7/site-packages/django/db/backends/schema.py", line 183, in effective_default
default = field.get_db_prep_save(default, self.connection)
File "/home/user/ve/myproject/local/lib/python2.7/site-packages/django/db/models/fields/__init__.py", line 627, in get_db_prep_save
prepared=False)
File "/home/user/ve/myproject/local/lib/python2.7/site-packages/django_pg/models/fields/uuid.py", line 83, in get_db_prep_value
prepared=prepared)
File "/home/user/ve/myproject/local/lib/python2.7/site-packages/django/db/models/fields/__init__.py", line 619, in get_db_prep_value
value = self.get_prep_value(value)
File "/home/user/ve/myproject/local/lib/python2.7/site-packages/django_pg/models/fields/uuid.py", line 64, in get_prep_value
raise ValueError('Explicit UUID required unless either `null` is '
ValueError: Explicit UUID required unless either `null` is True or `auto_add` is given.
Help, please :)
Thanks very much!
Hi @cheerzorpo, I'll look into this. Thanks!
I think you can get around the migration error with
import uuid
class MyModel(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4)
A better error message is probably necessary, also the default django fields let you define date time callables for new time fields, something like that isn't necessary but could be nice.
Hi @budlight,
This would require me to add default back every time I create a migration and take it off after the migration is applied, in order that I wouldn't have problems with admin inlines.
Plus, the exception says:
ValueError: Explicit UUID required unless either `null` is True or `auto_add` is given.
I did set auto_add=True in my example, so isn't this a bug anyway? :P
Thanks
not the same thing?
auto_add=True in contrast to default doesn't result in problems with admin inlines, but the exception in the migration process is being thrown even though the field has auto_add=True (which by the exception message doesn't supposed to happen)
I am having the same problem on Django 1.7 during migration. Adding a default value does fix the problem.
It looks like during the migration the migration process the auto_add parameter gets dropped (maybe has to do with deconstruct, I am not sure) but here is a dump of the value of auto_add and kwargs during a migration if it helps: True <-> {'default': <function uuid4 at 0x28c0cf8>, 'primary_key': True} False <-> {u'default': <function uuid4 at 0x28c0cf8>, u'serialize': False, u'unique': True, u'editable': False, u'primary_key': True} False <-> {u'default': <function uuid4 at 0x28c0cf8>, u'serialize': False, u'unique': True, u'editable': False, u'primary_key': True} False <-> {u'default': <function uuid4 at 0x28c0cf8>, u'serialize': False, u'unique': True, u'editable': False, u'primary_key': True} False <-> {u'default': <function uuid4 at 0x28c0cf8>, u'serialize': False, u'unique': True, u'editable': False, u'primary_key': True}