user422005
user422005

Reputation: 2041

Upgrade Django project to Python3 - migrations fail

I have a Django project which has been developed with Python2.7, it is currently using Django version 1.10. I am now in the process of upgrading - first to Python3, and then afterwards I will do the Django upgrade.

When I make Python3 virtual environment and run the tests:

venv bash% ./manage.py tests

I get a massive traceback:

Traceback (most recent call last):
  File "./manage.py", line 9, in <module>
    execute_from_command_line( sys.argv )
  File "/home/hove/sleipner/venv/lib/python3.5/site-packages/django/core/management/__init__.py", line 367, in execute_from_command_line
    utility.execute()
  File "/home/hove/sleipner/venv/lib/python3.5/site-packages/django/core/management/__init__.py", line 359, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/home/hove/sleipner/venv/lib/python3.5/site-packages/django/core/management/commands/test.py", line 29, in run_from_argv
    super(Command, self).run_from_argv(argv)
  File "/home/hove/sleipner/venv/lib/python3.5/site-packages/django/core/management/base.py", line 305, in run_from_argv
    self.execute(*args, **cmd_options)
  File "/home/hove/sleipner/venv/lib/python3.5/site-packages/django/core/management/base.py", line 356, in execute
    output = self.handle(*args, **options)
  File "/home/hove/sleipner/venv/lib/python3.5/site-packages/django/core/management/commands/test.py", line 72, in handle
    failures = test_runner.run_tests(test_labels)
  File "/home/hove/sleipner/venv/lib/python3.5/site-packages/django/test/runner.py", line 549, in run_tests
    old_config = self.setup_databases()
  File "/home/hove/sleipner/venv/lib/python3.5/site-packages/django/test/runner.py", line 499, in setup_databases
    self.parallel, **kwargs
  File "/home/hove/sleipner/venv/lib/python3.5/site-packages/django/test/runner.py", line 743, in setup_databases
    serialize=connection.settings_dict.get("TEST", {}).get("SERIALIZE", True),
  File "/home/hove/sleipner/venv/lib/python3.5/site-packages/django/db/backends/base/creation.py", line 70, in create_test_db
    run_syncdb=True,
  File "/home/hove/sleipner/venv/lib/python3.5/site-packages/django/core/management/__init__.py", line 130, in call_command
    return command.execute(*args, **defaults)
  File "/home/hove/sleipner/venv/lib/python3.5/site-packages/django/core/management/base.py", line 356, in execute
    output = self.handle(*args, **options)
  File "/home/hove/sleipner/venv/lib/python3.5/site-packages/django/core/management/commands/migrate.py", line 202, in handle
    targets, plan, fake=fake, fake_initial=fake_initial
  File "/home/hove/sleipner/venv/lib/python3.5/site-packages/django/db/migrations/executor.py", line 97, in migrate
    state = self._migrate_all_forwards(plan, full_plan, fake=fake, fake_initial=fake_initial)
  File "/home/hove/sleipner/venv/lib/python3.5/site-packages/django/db/migrations/executor.py", line 132, in _migrate_all_forwards
    state = self.apply_migration(state, migration, fake=fake, fake_initial=fake_initial)
  File "/home/hove/sleipner/venv/lib/python3.5/site-packages/django/db/migrations/executor.py", line 237, in apply_migration
    state = migration.apply(state, schema_editor)
  File "/home/hove/sleipner/venv/lib/python3.5/site-packages/django/db/migrations/migration.py", line 129, in apply
    operation.database_forwards(self.app_label, schema_editor, old_state, project_state)
  File "/home/hove/sleipner/venv/lib/python3.5/site-packages/django/db/migrations/operations/models.py", line 96, in database_forwards
    schema_editor.create_model(model)
  File "/home/hove/sleipner/venv/lib/python3.5/site-packages/django/db/backends/base/schema.py", line 271, in create_model
    self.quote_name(field.column),
  File "/home/hove/sleipner/venv/lib/python3.5/site-packages/django/db/backends/base/schema.py", line 115, in quote_name
    return self.connection.ops.quote_name(name)
  File "/home/hove/sleipner/venv/lib/python3.5/site-packages/django/db/backends/sqlite3/operations.py", line 153, in quote_name
    if name.startswith('"') and name.endswith('"'):
TypeError: startswith first arg must be bytes or a tuple of bytes, not str

As I understand it the problem is unicode/string issues in the migrations? I have tried to follow the advice: "Add from __future__ import unicode_literals at the top every module". The resulting code still works nicely in Python2.7, but manage.py test fails in the same way for Python3.

For all it is worth the project seems to "basically" work in Python3 when I do:

bash% manage.py runserver

Update:

These are my database settings - might very well be something wrong with this, but observe that it has worked in Python2.7 for many years - and still does:

if "test" in sys.argv:
    DATABASES = { 'default' : {
        "ENGINE" : "django.db.backends.sqlite3",
        "NAME" : "friskby.sqlite",
        "TEST" : {
            "NAME" : "friskby-test.sqlite"}}}
else:
    DATABASE_URL = os.environ.get("DATABASE_URL")
    if DATABASE_URL:
        config = dj_database_url.config(default = DATABASE_URL)
        DATABASES = { 'default': config }
    else:
        raise Exception("The DATABASE_URL environment variable has not bee set")

Upvotes: 3

Views: 1366

Answers (1)

user422005
user422005

Reputation: 2041

The comment from @Will Keeling set me on the right track. My migrations (originally created with Python2.7) had many:

... db_column = b"NAME_OF_COLUMN", ...

statements. I just removed all the leading b - and lo and behold all tests pass in both Python2.7 and Python3.

Upvotes: 5

Related Questions