#34946: Adding a field with default and db_default drops database level DEFAULT
-------------------------------------------+--------------------------
               Reporter:  Simon Charette   |          Owner:  nobody
                   Type:  Bug              |         Status:  assigned
              Component:  Migrations       |        Version:  5.0
               Severity:  Release blocker  |       Keywords:
           Triage Stage:  Unreviewed       |      Has patch:  0
    Needs documentation:  0                |    Needs tests:  0
Patch needs improvement:  0                |  Easy pickings:  0
                  UI/UX:  0                |
-------------------------------------------+--------------------------
 [https://docs.djangoproject.com/en/dev/ref/models/fields/#db-default The
 documentation] for `Field.db_default` states

 > If both `db_default` and `Field.default` are set, `default` will take
 precedence when creating instances in Python code. `db_default` will still
 be set at the database level and will be used when inserting rows outside
 of the ORM or when adding a new field in a migration.

 However adding a field with both results in the following SQL

 {{{#!sql
 ALTER TABLE "foo" ADD COLUMN "bar" integer DEFAULT 42 NOT NULL;
 ALTER TABLE "foo" ALTER COLUMN "bar" DROP DEFAULT;
 }}}

 The `DEFAULT` should never be dropped if the field has a `db_default`
 defined.

 The following patch reproduces and demonstrate
 
[https://github.com/django/django/commit/7414704e88d73dafbcfbb85f9bc54cb6111439d3
 #diff-
 7cc40f1cb85a8f19c80b2e901626d78e4729047dbbb0ed52861f5894ff688115R1673-R1716
 why the test] that intended to cover this case didn't catch it.

 {{{#!diff
 diff --git a/tests/migrations/test_operations.py
 b/tests/migrations/test_operations.py
 index d58da8b7ac..57a9086c19 100644
 --- a/tests/migrations/test_operations.py
 +++ b/tests/migrations/test_operations.py
 @@ -1692,15 +1692,22 @@ def test_add_field_both_defaults(self):
          field = new_state.models[app_label, "pony"].fields["height"]
          self.assertEqual(field.default, 3)
          self.assertEqual(field.db_default, Value(4))
 -        project_state.apps.get_model(app_label,
 "pony").objects.create(weight=4)
 +        pre_pony_pk = (
 +            project_state.apps.get_model(app_label,
 "pony").objects.create(weight=4).pk
 +        )
          self.assertColumnNotExists(table_name, "height")
          # Add field.
          with connection.schema_editor() as editor:
              operation.database_forwards(app_label, editor, project_state,
 new_state)
          self.assertColumnExists(table_name, "height")
 +        post_pony_pk = (
 +            project_state.apps.get_model(app_label,
 "pony").objects.create(weight=10).pk
 +        )
          new_model = new_state.apps.get_model(app_label, "pony")
 -        old_pony = new_model.objects.get()
 -        self.assertEqual(old_pony.height, 4)
 +        pre_pony = new_model.objects.get(pk=pre_pony_pk)
 +        self.assertEqual(pre_pony.height, 4)
 +        post_pony = new_model.objects.get(pk=post_pony_pk)
 +        self.assertEqual(post_pony.height, 4)
          new_pony = new_model.objects.create(weight=5)
          if not connection.features.can_return_columns_from_insert:
              new_pony.refresh_from_db()
 diff --git a/tests/schema/tests.py b/tests/schema/tests.py
 index 20a00e29f7..80fdead190 100644
 --- a/tests/schema/tests.py
 +++ b/tests/schema/tests.py
 @@ -2257,6 +2257,24 @@ class Meta:
          columns = self.column_classes(AuthorDbDefault)
          self.assertEqual(columns["renamed_year"][1].default, "1985")

 +    @isolate_apps("schema")
 +    def test_add_field_both_defaults_preserves_db_default(self):
 +        class Author(Model):
 +            class Meta:
 +                app_label = "schema"
 +
 +        #self.isolated_local_models = [Author]
 +        with connection.schema_editor() as editor:
 +            editor.create_model(Author)
 +
 +        field = IntegerField(default=1985, db_default=1988)
 +        field.set_attributes_from_name("birth_year")
 +        field.model = Author
 +        with connection.schema_editor() as editor:
 +            editor.add_field(Author, field)
 +        columns = self.column_classes(Author)
 +        self.assertEqual(columns["birth_year"][1].default, "1988")
 +
      @skipUnlessDBFeature(
          "supports_column_check_constraints",
 "can_introspect_check_constraints"
      )
 }}}

-- 
Ticket URL: <https://code.djangoproject.com/ticket/34946>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/0107018ba07f1f7d-72f477d7-e78f-4c1f-83e7-f851ab1aa329-000000%40eu-central-1.amazonses.com.

Reply via email to