#25068: Metaclass conflict when doing createmigrations in ModelState.render
-------------------------+-------------------------------------------------
Reporter: kosz85 | Owner: nobody
Type: | Status: new
Uncategorized |
Component: | Version: 1.8
Migrations |
Severity: Release | Keywords: metaclass conflict createmigrations
blocker |
Triage Stage: | Has patch: 0
Unreviewed |
Easy pickings: 0 | UI/UX: 0
-------------------------+-------------------------------------------------
I'm migrating my project from Django 1.6.x to 1.8.2, I found this bug and
fix for it.
In my project I'm using few ModelMixins with custom {{{__metadata__}}},
problem is that render is trying do a class using {{{type}}} but this code
forgot about python class metadata multi inheritance.
Traceback looks like this, for each model with more complex metadata:
{{{
$ /manage.py makemigrations
(...)
Traceback (most recent call last):
File "/home/vagrant/***/manage.py", line 10, in <module>
execute_from_command_line(sys.argv)
File "/home/vagrant/env/local/lib/python2.7/site-
packages/django/core/management/__init__.py", line 338, in
execute_from_command_line
utility.execute()
File "/home/vagrant/env/local/lib/python2.7/site-
packages/django/core/management/__init__.py", line 330, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/home/vagrant/env/local/lib/python2.7/site-
packages/django/core/management/base.py", line 390, in run_from_argv
self.execute(*args, **cmd_options)
File "/home/vagrant/env/local/lib/python2.7/site-
packages/django/core/management/base.py", line 441, in execute
output = self.handle(*args, **options)
File "/home/vagrant/env/local/lib/python2.7/site-
packages/django/core/management/commands/makemigrations.py", line 125, in
handle
migration_name=self.migration_name,
File "/home/vagrant/env/local/lib/python2.7/site-
packages/django/db/migrations/autodetector.py", line 43, in changes
changes = self._detect_changes(convert_apps, graph)
File "/home/vagrant/env/local/lib/python2.7/site-
packages/django/db/migrations/autodetector.py", line 110, in
_detect_changes
self.old_apps = self.from_state.concrete_apps
File "/home/vagrant/env/local/lib/python2.7/site-
packages/django/db/migrations/state.py", line 170, in concrete_apps
self.apps = StateApps(self.real_apps, self.models,
ignore_swappable=True)
File "/home/vagrant/env/local/lib/python2.7/site-
packages/django/db/migrations/state.py", line 232, in __init__
self.render_multiple(list(models.values()) + self.real_models)
File "/home/vagrant/env/local/lib/python2.7/site-
packages/django/db/migrations/state.py", line 262, in render_multiple
model.render(self)
File "/home/vagrant/env/local/lib/python2.7/site-
packages/django/db/migrations/state.py", line 548, in render
body,
TypeError: metaclass conflict: the metaclass of a derived class must be a
(non-strict) subclass of the metaclasses of all its bases
}}}
Fix is simple. I used classmaker from here
http://code.activestate.com/recipes/204197-solving-the-metaclass-conflict/
And replaced line 543 of db/migrations/state.py from this:
{{{
# Then, make a Model object (apps.register_model is called in
__new__)
return type(
str(self.name),
bases,
body,
)
}}}
to this:
{{{
# Then, make a Model object (apps.register_model is called in
__new__)
from lib.utils.meta_maker import classmaker
return classmaker()(str(self.name), bases, body)
}}}
My lib.utils.meta_maker is code from link I provided, with little changes.
This way it works without a problems as metaclases are handled properly.
Classmaker in most cases will return type, but for my more complex models
will do the magic.
--
Ticket URL: <https://code.djangoproject.com/ticket/25068>
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 [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-updates/049.802bbc215097db8cce7b65e647434b7e%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.