[PATCH 3/3] migrations: Add the default value of Patch.state

Damien Lespiau damien.lespiau at intel.com
Fri Aug 21 02:13:49 AEST 2015


Now that we have migration 0002 populating the db with the intial list
of states, we can add the default Patch.state value (which depends on
being able to query the state with ordering=0).

Of course, it's not that simple and I was hitting an exception

  Applying patchwork.0003_patch_state_default_value...Traceback (most recent call last):
  [...]
  File "django/db/migrations/executor.py", line 148, in apply_migration
    state = migration.apply(state, schema_editor)
  File "django/db/migrations/migration.py", line 115, in apply
    operation.database_forwards(self.app_label, schema_editor, old_state, project_state)
  File "django/db/migrations/operations/fields.py", line 201, in database_forwards
    schema_editor.alter_field(from_model, from_field, to_field)
  File "django/db/backends/base/schema.py", line 484, in alter_field
    old_db_params, new_db_params, strict)
  File "django/db/backends/base/schema.py", line 567, in _alter_field
    new_default = self.effective_default(new_field)
  File "django/db/backends/base/schema.py", line 211, in effective_default
    default = field.get_db_prep_save(default, self.connection)
  File "django/db/models/fields/related.py", line 1956, in get_db_prep_save
    return self.related_field.get_db_prep_save(value, connection=connection)
  File "django/db/models/fields/__init__.py", line 710, in get_db_prep_save
    prepared=False)
  File "django/db/models/fields/__init__.py", line 977, in get_db_prep_value
    value = self.get_prep_value(value)
  File "django/db/models/fields/__init__.py", line 985, in get_prep_value
    return int(value)
  TypeError: int() argument must be a string or a number, not 'State'

Django was trying to make an int out of the State instance returned by
get_default_initial_patch_state(). Turns out I wasn't the first one to
hit that:

  "Migration crash on ForeignKey with a callable default that returns a
   model instance"

  Source: https://code.djangoproject.com/ticket/25129

And the solution decided by the django developers was to restrict what
callable defaults can return with ForeignKeys:

  "For fields like ForeignKey that map to model instances, defaults
   should be the value of the field they reference (pk unless to_field is
   set) instead of model instances."

  Source: https://docs.djangoproject.com/en/dev/ref/models/fields/#default

v2: Don't change get_default_initial_patch_state() as it's used outside
    of models.py

Signed-off-by: Damien Lespiau <damien.lespiau at intel.com>
---
 .../migrations/0003_patch_state_default_value.py     | 20 ++++++++++++++++++++
 patchwork/models.py                                  |  5 ++++-
 2 files changed, 24 insertions(+), 1 deletion(-)
 create mode 100644 patchwork/migrations/0003_patch_state_default_value.py

diff --git a/patchwork/migrations/0003_patch_state_default_value.py b/patchwork/migrations/0003_patch_state_default_value.py
new file mode 100644
index 0000000..3324406
--- /dev/null
+++ b/patchwork/migrations/0003_patch_state_default_value.py
@@ -0,0 +1,20 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import models, migrations
+import patchwork.models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('patchwork', '0002_load_initial_data'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='patch',
+            name='state',
+            field=models.ForeignKey(default=patchwork.models.get_default_initial_patch_state_pk, to='patchwork.State'),
+        ),
+    ]
diff --git a/patchwork/models.py b/patchwork/models.py
index c2b8a9c..4a1a432 100644
--- a/patchwork/models.py
+++ b/patchwork/models.py
@@ -205,6 +205,9 @@ class PatchTag(models.Model):
 def get_default_initial_patch_state():
     return State.objects.get(ordering=0)
 
+def get_default_initial_patch_state_pk():
+    return get_default_initial_patch_state().pk
+
 class PatchQuerySet(models.query.QuerySet):
 
     def with_tag_counts(self, project):
@@ -243,7 +246,7 @@ class Patch(models.Model):
     date = models.DateTimeField(default=datetime.datetime.now)
     submitter = models.ForeignKey(Person)
     delegate = models.ForeignKey(User, blank = True, null = True)
-    state = models.ForeignKey(State, default=get_default_initial_patch_state)
+    state = models.ForeignKey(State, default=get_default_initial_patch_state_pk)
     archived = models.BooleanField(default = False)
     headers = models.TextField(blank = True)
     content = models.TextField(null = True, blank = True)
-- 
2.1.0



More information about the Patchwork mailing list