Changes between Initial Version and Version 7 of Ticket #29632


Ignore:
Timestamp:
Aug 5, 2018, 11:39:20 PM (6 years ago)
Author:
Florian Mayer
Comment:

Legend:

Unmodified
Added
Removed
Modified
  • Ticket #29632

    • Property Resolutionneedsinfo
    • Property Status newclosed
    • Property Summary After migrating a Django project from Python 2 to 3, db migration of django.contrib.sites fails with "TypeError: attribute name must be string, not 'bytes'"After migrating a Django project generated with cookiecutter-django from Python 2.x to 3.x, db migration of (cookiecutter-django generated, not Django module) django.contrib.sites fails with "TypeError: attribute name must be string, not 'bytes'"
  • Ticket #29632 – Description

    initial v7  
    1010* The migrations were created using Django 1.9.7 to 1.11.x
    1111* Third party app migrations are potentially ancient
     12* Project generated by cookiecutter-django, which generates a stand-alone contrib.sites app ([https://cookiecutter-django.readthedocs.io/en/latest/faq.html#why-is-there-a-django-contrib-sites-directory-in-cookiecutter-django rationale here])
     13* '''Solution: There was a stray bytestring in cookiecutter-django's contrib.sites migration.'''
    1214
    1315== Stack trace ==
     
    7880}}}
    7981tl;dr: The `name`, a value coming from the migration `sites.0001_initial`, was interpreted by `setattr(model, name, ManagerDescriptor(self))` as a bytestring.
     82Confusingly, this migration was inside the project, not inside django.contrib.sites.
    8083
    8184== Steps in detail ==
     
    8386* While running `./manage.py migrate`, the [https://github.com/django/django/blob/master/django/db/models/manager.py#L113 django.db.models.manager L113] reads the migration's model manager name expecting a unicode string, and not defending against a bytestring.
    8487
    85 
    8688I was able to fix my own existing migrations (created in Django 1.x) either by hand (inserting the `unicode_literals` import, or deleting the occasional explicit `b""` prefix), or by squashing multiple migrations (where too numerous to manually edit) under Django 2.x, which inserted the `unicode_literals` statement into my newly created migrations.
    8789However, this approach won't work with third party migrations without manually patching them (which won't work on e.g. CI and is brittle) or forking (creating a maintenance trail for me).
    8890
    8991== Suggested patches ==
    90 * Primarily, add `from __future__ import unicode_literals` to django.contrib.sites' [https://github.com/django/django/blob/master/django/contrib/sites/migrations/0001_initial.py migration 0001].
     92* ~~Primarily, add `from __future__ import unicode_literals` to django.contrib.sites' [https://github.com/django/django/blob/master/django/contrib/sites/migrations/0001_initial.py migration 0001].~~
    9193* As a longer term fix, replace [https://github.com/django/django/blob/master/django/db/models/manager.py#L113 django.db.models.manager L113] `setattr(model, name, ManagerDescriptor(self))` with `setattr(model, force_text(name), ManagerDescriptor(self))` (and import `force_text`).
    92 * If a bytestring is found, a Django warning should prompt the user to clean up the offending migration by adding the `unicode_literals` import. This would be more graceful and efficient than presenting the TypeError.
     94* If a bytestring is found, a Django warning should prompt the user to clean up the offending migration ~~by adding the `unicode_literals` import~~. This would be more graceful and efficient than presenting the TypeError.
    9395
    9496The benefit of patching db.models.manager would be that all Python 2.x-style migrations, especially of third party packages, would work in Python 3.x-based Django projects without the need to patch them.
    9597
    96 Has anyone else encountered this bug? Happy to PR whichever fix is deemed most appropriate (bear with me, first Django bug report).
     98~~Has anyone else encountered this bug? Happy to PR whichever fix is deemed most appropriate (bear with me, first Django bug report).~~
Back to Top