Opened 5 years ago

Closed 5 years ago

Last modified 5 years ago

#23418 closed Cleanup/optimization (fixed)

Classes embedded inside other classes are not serialized correctly

Reported by: Dan Loewenherz Owned by: Markus Holtermann
Component: Migrations Version: 1.7
Severity: Normal Keywords:
Cc: info+coding@… Triage Stage: Unreviewed
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

Simple example:

class Store(models.Model):
    @deconstructible
    class IgnoreFormatString(object):
        def __init__(self, s):
            self.s = s

        def __str__(self):
            return self.s

        def __mod__(self, k):
            return self

    name = models.CharField(max_length=64, null=True)
    rating = models.IntegerField(error_messages={'invalid': IgnoreFormatString("You've entered an invalid value.")}, null=True)

The migration is created appropriately, but running it will fail with something like the following:

Traceback (most recent call last):
  File "./manage.py", line 10, in <module>
    execute_from_command_line(sys.argv)
  File "my_project/lib/python2.7/site-packages/django/core/management/__init__.py", line 385, in execute_from_command_line
    utility.execute()
  File "my_project/lib/python2.7/site-packages/django/core/management/__init__.py", line 377, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "my_project/lib/python2.7/site-packages/django/core/management/base.py", line 288, in run_from_argv
    self.execute(*args, **options.__dict__)
  File "my_project/lib/python2.7/site-packages/django/core/management/base.py", line 338, in execute
    output = self.handle(*args, **options)
  File "my_project/lib/python2.7/site-packages/django/core/management/commands/migrate.py", line 63, in handle
    executor = MigrationExecutor(connection, self.migration_progress_callback)
  File "my_project/lib/python2.7/site-packages/django/db/migrations/executor.py", line 17, in __init__
    self.loader = MigrationLoader(self.connection)
  File "my_project/lib/python2.7/site-packages/django/db/migrations/loader.py", line 48, in __init__
    self.build_graph()
  File "my_project/lib/python2.7/site-packages/django/db/migrations/loader.py", line 173, in build_graph
    self.load_disk()
  File "my_project/lib/python2.7/site-packages/django/db/migrations/loader.py", line 103, in load_disk
    migration_module = import_module("%s.%s" % (module_name, migration_name))
  File "/usr/local/Cellar/python/2.7.6/Frameworks/Python.framework/Versions/2.7/lib/python2.7/importlib/__init__.py", line 37, in import_module
    __import__(name)
  File "my_project/app/migrations/0001_initial.py", line 8, in <module>
    class Migration(migrations.Migration):
  File "my_project/app/migrations/0001_initial.py", line 19, in Migration
    ('rating', models.IntegerField(null=True, error_messages={b'invalid': app.models.IgnoreFormatString(b"You've entered an invalid value.")})),
AttributeError: 'module' object has no attribute 'IgnoreFormatString

Let me know if you need anything else to help diagnose the issue or have any questions. Cheers!

Change History (13)

comment:1 Changed 5 years ago by Andrew Godwin

Resolution: invalid
Status: newclosed

Unfortunately, this is unserializable, as there's no way to get the reference to the surrounding class from the inner class. I'll update the docs to mention this, but the only fix for you is to move InvalidFormatString to the outer scope.

comment:2 Changed 5 years ago by Andrew Godwin <andrew@…>

In 45768e6b72607b4bc913358c560830454f3336a7:

Update docs to be more clear about nested classes (refs #23418)

comment:3 Changed 5 years ago by Andrew Godwin <andrew@…>

In e5cdfb151039cdd22a17480f0f1fb9ccbad5eb56:

[1.7.x] Update docs to be more clear about nested classes (refs #23418)

comment:4 Changed 5 years ago by Dan Loewenherz

@Andrew Any way we can prevent the migration itself from being created as well? Although the docs mention it now, the migration is still created and users won't encounter the error until after running it. Thoughts?

comment:5 Changed 5 years ago by Dan Loewenherz

Resolution: invalid
Status: closednew

Reopening since I'm not convinced a doc-only change is sufficient. I'm happy to contribute a patch if needed.

comment:6 Changed 5 years ago by Markus Holtermann

Cc: info+coding@… added
Has patch: set
Owner: changed from nobody to Markus Holtermann
Status: newassigned
Type: BugCleanup/optimization

comment:7 Changed 5 years ago by Dan Loewenherz

Awesome, thanks!

comment:8 Changed 5 years ago by Markus Holtermann <info@…>

Resolution: fixed
Status: assignedclosed

In d28b5f13b332bda4317949b98e33f528d30ec006:

Fixed #23418 -- Fail when migration deconstruct produces invalid import

comment:9 Changed 5 years ago by Tim Graham <timograham@…>

In b0def3bcac1a2e1117050e00fa1b187a897f0c2e:

[1.7.x] Fixed #23418 -- Fail when migration deconstruct produces invalid import

Backport of d28b5f13b3 from master

comment:10 Changed 5 years ago by Tim Graham <timograham@…>

In 16548cfc7c9d86ae7b0d13425ec7608f0571130c:

Fixed broken test from da160d440f; refs #23418.

comment:11 Changed 5 years ago by Tim Graham <timograham@…>

In 1f1a32928873a4e7cfe2f8f15631aa63df335490:

[1.7.x] Fixed broken test from da160d440f; refs #23418.

Backport of 16548cfc7c from master

comment:12 Changed 5 years ago by Tim Graham <timograham@…>

In fbeb7979ee43cb386265ff7aec757e35b4cf61f8:

Avoided using deprecated version of importlib; refs #23418.

comment:13 Changed 5 years ago by Tim Graham <timograham@…>

In 4500784b24856b23924e7d36b405f2df1499ea83:

[1.7.x] Avoided using deprecated version of importlib; refs #23418.

Backport of fbeb7979ee from master

Note: See TracTickets for help on using tickets.
Back to Top