#23226: Migrations generated by python2 break when using python3 to migrate
---------------------------------+----------------------------------------
     Reporter:  morshed.nader@…  |                    Owner:  andrewgodwin
         Type:  Bug              |                   Status:  assigned
    Component:  Migrations       |                  Version:  1.7-rc-2
     Severity:  Release blocker  |               Resolution:
     Keywords:                   |             Triage Stage:  Accepted
    Has patch:  0                |      Needs documentation:  0
  Needs tests:  0                |  Patch needs improvement:  0
Easy pickings:  0                |                    UI/UX:  0
---------------------------------+----------------------------------------

Comment (by charettes):

 Replying to [comment:6 andrewgodwin]:
 > I'm in two minds as to whether we should just force-convert everything
 to Unicode in migration files (which obviously is technically changing
 data, and might break with strings intended for humans to read), or
 document that you should be using unicode for your models files.
 >
 > There's a potential third outcome here where we fix the state stuff to
 convert all model names/field names to unicode, which would solve most
 immediate problems. I'll investigate.

 The thing is that it's hard to which part needs fixing to solve the
 immediate problem. Take `order_with_respect_to` for example:

 {{{#!python
 # models.py
 from django.db import models

 class A(models.Model): pass

 class B(models.Model):
     a = models.ForeignKey(A)

     class Meta:
         order_with_respect_to = 'a'
 }}}

 {{{#!python
 # migrations/0001_initial.py (generated on Py2)
 from __future__ import unicode_literals

 from django.db import models, migrations


 class Migration(migrations.Migration):

     dependencies = [
     ]

     operations = [
         migrations.CreateModel(
             name='A',
             fields=[
                 ('id', models.AutoField(verbose_name='ID',
 serialize=False, auto_created=True, primary_key=True)),
             ],
             options={
             },
             bases=(models.Model,),
         ),
         migrations.CreateModel(
             name='B',
             fields=[
                 ('id', models.AutoField(verbose_name='ID',
 serialize=False, auto_created=True, primary_key=True)),
                 ('a', models.ForeignKey(to='app.A')),
             ],
             options={
             },
             bases=(models.Model,),
         ),
         migrations.AlterOrderWithRespectTo(
             name='b',
             order_with_respect_to=b'a',
         ),
     ]
 }}}

 It would also fail with a similar exception when migration on Python 3

 {{{#!python
 Operations to perform:
   Apply all migrations: auth, app, sessions, contenttypes, migratemodule,
 admin
 Running migrations:
   Applying app.0001_initial...Traceback (most recent call last):
   File "./manage.py", line 11, in <module>
     execute_from_command_line(sys.argv)
   File "/home/simon/workspace/django/django/core/management/__init__.py",
 line 330, in execute_from_command_line
     utility.execute()
   File "/home/simon/workspace/django/django/core/management/__init__.py",
 line 322, in execute
     self.fetch_command(subcommand).run_from_argv(self.argv)
   File "/home/simon/workspace/django/django/core/management/base.py", line
 363, in run_from_argv
     self.execute(*args, **cmd_options)
   File "/home/simon/workspace/django/django/core/management/base.py", line
 413, in execute
     output = self.handle(*args, **options)
   File
 "/home/simon/workspace/django/django/core/management/commands/migrate.py",
 line 160, in handle
     executor.migrate(targets, plan, fake=options.get("fake", False))
   File "/home/simon/workspace/django/django/db/migrations/executor.py",
 line 63, in migrate
     self.apply_migration(migration, fake=fake)
   File "/home/simon/workspace/django/django/db/migrations/executor.py",
 line 91, in apply_migration
     if self.detect_soft_applied(migration):
   File "/home/simon/workspace/django/django/db/migrations/executor.py",
 line 135, in detect_soft_applied
     apps = project_state.render()
   File "/home/simon/workspace/django/django/db/migrations/state.py", line
 67, in render
     model.render(self.apps)
   File "/home/simon/workspace/django/django/db/migrations/state.py", line
 292, in render
     body,
   File "/home/simon/workspace/django/django/db/models/base.py", line 287,
 in __new__
     new_class._prepare()
   File "/home/simon/workspace/django/django/db/models/base.py", line 312,
 in _prepare
     opts._prepare(cls)
   File "/home/simon/workspace/django/django/db/models/options.py", line
 170, in _prepare
     self.order_with_respect_to =
 self.get_field(self.order_with_respect_to)
   File "/home/simon/workspace/django/django/db/models/options.py", line
 388, in get_field
     raise FieldDoesNotExist('%s has no field named %r' %
 (self.object_name, name))
 django.db.models.fields.FieldDoesNotExist: B has no field named b'a'
 }}}

 I think that all field and model options referring to field names somehow
 should be converted to `six.text_type`. Idem with `dict` based options
 (such as `limit_choices_to`) that might be passed as `**kwargs` or string
 based ones that might end up as a kwarg name since `callable(**{b'key':
 'value'})` isn't allowed on Python 3 (While both `bytes` and `unicode`
 kwarg is allowed on Python 2).

 Since those criteria covers most of the existing field and model options I
 suggest we convert all of them (during deconstruction) instead of trying
 to guess every possible places where this option might be referenced.

 This alternative might also help mitigate issues users on Python 2
 creating migrations and then later trying to move to Python 3 would
 encounter.

-- 
Ticket URL: <https://code.djangoproject.com/ticket/23226#comment:7>
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/081.a141eac99c0bacc1cccd11ef83cb3de3%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to