#26739: Backward operation for RemoveField does not allow a default value in 
case
the field is not null.
----------------------------+--------------------
     Reporter:  Gagaro      |      Owner:  nobody
         Type:  Bug         |     Status:  new
    Component:  Migrations  |    Version:  master
     Severity:  Normal      |   Keywords:
 Triage Stage:  Unreviewed  |  Has patch:  0
Easy pickings:  0           |      UI/UX:  0
----------------------------+--------------------
 If a field does not allow NULL and has no default, and this field is
 removed using RemoveField, the backward operation will break if the
 database is populated because the field will be created with no value.

 Replication:

 models.py
 {{{
 class TestModel(Model):
     field = CharField(max_length=255)
 }}}

 {{{
 $ python manage.py makemigrations
 $ python manage.py migrate
 $ python manage.py shell
 >>> TestModel.objects.create(field='test')
 }}}

 models.py
 {{{
 class TestModel(Model):
     pass
 }}}

 {{{
 $ python manage.py makemigrations
 $ python manage migrate
 $ python manage migrate app 0001
 }}}

 POC Patch made by apollo13 in IRC:

 {{{
 diff --git a/django/db/migrations/operations/fields.py
 b/django/db/migrations/operations/fields.py
 index 041f8a6..5604e36 100644
 --- a/django/db/migrations/operations/fields.py
 +++ b/django/db/migrations/operations/fields.py
 @@ -122,6 +122,10 @@ class RemoveField(FieldOperation):
      Removes a field from a model.
      """

 +    def __init__(self, *args, **kwargs):
 +        self.default = kwargs.pop('default', None)
 +        super(RemoveField, self).__init__(*args, **kwargs)
 +
      def deconstruct(self):
          kwargs = {
              'model_name': self.model_name,
 @@ -150,7 +154,12 @@ class RemoveField(FieldOperation):
          to_model = to_state.apps.get_model(app_label, self.model_name)
          if self.allow_migrate_model(schema_editor.connection.alias,
 to_model):
              from_model = from_state.apps.get_model(app_label,
 self.model_name)
 -            schema_editor.add_field(from_model,
 to_model._meta.get_field(self.name))
 +            to_field = to_model._meta.get_field(self.name)
 +            old_default = to_field.default
 +            if self.default is not None:
 +                to_field.default = self.default
 +            schema_editor.add_field(from_model, to_field)
 +            to_field.default = old_default

      def describe(self):
          return "Remove field %s from %s" % (self.name, self.model_name)
 }}}

--
Ticket URL: <https://code.djangoproject.com/ticket/26739>
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 django-updates+unsubscr...@googlegroups.com.
To post to this group, send email to django-updates@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/049.a8876754e6f019b3f513d4849e4e00ac%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to